Планировщик задач на MikroTik — /system/scheduler
Планировщик задач MikroTik (scheduler) — встроенный cron-аналог в RouterOS, позволяющий запускать скрипты и команды по расписанию без внешних инструментов. Модуль /system/scheduler доступен на всех устройствах MikroTik с RouterOS 7.x и выше, включает поддержку интервальных, одноразовых и стартовых задач. Планировщик — ключевой компонент автоматизации: от ежедневного backup конфигурации до обновления DNS blacklist и отправки уведомлений в Telegram. В отличие от cron в Linux, scheduler в RouterOS использует интервальную модель (а не cron-выражения), что делает его проще для базовых сценариев, но требует другого подхода к сложным расписаниям. В этом руководстве подробно разберём создание задач, все параметры scheduler, 10 практических примеров, связку со скриптами, мониторинг и типичные ошибки.
Описание
Что такое /system/scheduler
/system/scheduler — подсистема RouterOS, которая выполняет указанный код (inline-команду или вызов скрипта из /system/script) в заданное время или с заданным интервалом. Scheduler работает на уровне ядра RouterOS и не зависит от наличия подключённых пользователей — задачи выполняются даже если к роутеру никто не подключён.
Scheduler решает три ключевые задачи:
| Задача | Описание | Пример |
|---|---|---|
| Периодические действия | Выполнение команды каждые N минут/часов/дней | Backup каждые 24 часа |
| Одноразовые действия | Выполнение команды в определённую дату и время | Перезагрузка в 03:00 в ночь на воскресенье |
| Действия при старте | Выполнение команды при загрузке RouterOS | Отправка уведомления о перезагрузке |
Как работает scheduler
При создании задачи RouterOS сохраняет её в конфигурацию. Внутренний таймер каждую секунду проверяет, наступило ли время выполнения. Когда время наступает:
- RouterOS проверяет
policyзадачи — хватает ли прав - Выполняет код из поля
on-eventв контексте виртуального пользователя с указанными policy - Увеличивает счётчик
run-countна 1 - Рассчитывает
next-runна основеinterval - Если
intervalне задан — задача остаётся, но больше не выполняется (одноразовая)
code[Создание задачи] │ ▼ [RouterOS таймер — проверка каждую секунду] │ ├── Время не наступило → ожидание │ └── Время наступило → ├── Проверка policy ├── Выполнение on-event ├── Обновление run-count └── Расчёт next-run (если есть interval)
Scheduler vs cron: сравнение
| Критерий | MikroTik Scheduler | Linux cron |
|---|---|---|
| Формат расписания | interval (1h, 1d, 00:05:00) | cron-выражение (*/5 * * * *) |
| Запуск «каждый понедельник в 8:00» | start-date (Mon) + interval=7d | 0 8 * * 1 |
| Запуск при старте системы | start-time=startup | @reboot |
| Минимальный интервал | 1 секунда | 1 минута |
| Управление правами | policy (ftp, read, write...) | пользователь crontab |
| Логирование | :log + /log/print | syslog / journald |
| Зависимость от NTP | Да (для start-date/start-time) | Да |
| Редактирование | CLI / WinBox / WebFig | crontab -e |
Терминология
| Термин | Описание |
|---|---|
| name | Уникальное имя задачи в scheduler |
| on-event | Код для выполнения — inline-команда или имя скрипта из /system/script |
| interval | Интервал повторения (0 = одноразовая задача) |
| start-date | Дата первого запуска (jan/01/2025) |
| start-time | Время первого запуска или «startup» для запуска при загрузке |
| policy | Набор прав, с которыми выполняется код |
| run-count | Счётчик: сколько раз задача была выполнена |
| next-run | Рассчитанное время следующего запуска |
Настройка
Создание задачи scheduler
Базовый синтаксис создания задачи:
[admin@MikroTik] >/system/scheduler add name=my-task interval=1d \ start-time=03:00:00 \ on-event="/export file=backup" \ policy=read,write,ftp,sensitive \ comment="Daily backup at 03:00"
Параметры scheduler
Полная таблица параметров /system/scheduler add:
| Параметр | Тип | По умолчанию | Описание |
|---|---|---|---|
| name | string | (обязательный) | Уникальное имя задачи |
| on-event | string | (обязательный) | Команда или имя скрипта для выполнения |
| start-date | date | текущая дата | Дата первого запуска (jan/01/2025) |
| start-time | time / startup | текущее время | Время первого запуска или startup |
| interval | time | 00:00:00 (одноразовая) | Интервал повторения |
| policy | list | read,write,policy,test | Права выполнения (через запятую) |
| disabled | yes/no | no | Отключить задачу без удаления |
| comment | string | (пусто) | Описание задачи |
Параметр policy — права выполнения
Policy определяет, какие команды может выполнять задача. Это критически важный параметр безопасности:
| Policy | Описание | Когда нужен |
|---|---|---|
| read | Чтение конфигурации | Почти всегда |
| write | Изменение конфигурации | Добавление/удаление правил, маршрутов |
| ftp | Доступ к файловой системе | Backup, запись файлов, /tool/fetch |
| reboot | Перезагрузка и выключение | /system/reboot |
| policy | Управление пользователями | Изменение паролей, создание пользователей |
| test | Запуск тестовых утилит | Ping, traceroute, bandwidth-test |
| password | Изменение своего пароля | Редко используется в скриптах |
| sniff | Packet sniffer | /tool/sniffer |
| sensitive | Доступ к чувствительным данным | Чтение паролей, ключей |
| romon | Доступ к RoMON | Управление соседними устройствами |
Принцип минимальных привилегий: назначайте только те policy, которые действительно нужны задаче. Backup-задача не нуждается в reboot, задача мониторинга не нуждается в write.
Типы расписания
Scheduler поддерживает три основных типа расписания.
Тип 1: По интервалу (периодическая задача)
Задача повторяется каждые N секунд/минут/часов/дней. Первый запуск — в указанное start-time.
[admin@MikroTik] ># Каждые 6 часов, начиная с 00:00 /system/scheduler add name=every-6h \ start-time=00:00:00 interval=6h \ on-event=":log info \"Running every 6 hours\"" \ policy=read,write
Тип 2: Одноразовая задача
Задача выполняется один раз в указанное время. Поле interval остаётся пустым (00:00:00).
[admin@MikroTik] ># Одноразовая перезагрузка в 03:00 5 января 2025 /system/scheduler add name=one-time-reboot \ start-date=jan/05/2025 start-time=03:00:00 \ on-event="/system/reboot" \ policy=read,reboot
После выполнения задача остаётся в списке с run-count=1 и next-run пустым. Её можно удалить вручную.
Тип 3: При старте системы (startup)
Задача выполняется каждый раз при загрузке RouterOS. Полезно для инициализации, уведомлений, восстановления состояния.
[admin@MikroTik] ># Отправка уведомления при загрузке /system/scheduler add name=on-boot-notify \ start-time=startup interval=0 \ on-event=":log warning \"Router rebooted at \$[/system/clock/get time]\"" \ policy=read,write
При использовании start-time=startup с interval > 0 задача выполнится при загрузке, а затем будет повторяться с указанным интервалом.
Форматы interval
| Формат | Значение | Пример |
|---|---|---|
Ns | N секунд | 30s — каждые 30 секунд |
Nm | N минут | 5m — каждые 5 минут |
Nh | N часов | 6h — каждые 6 часов |
Nd | N дней | 1d — каждые 24 часа |
HH:MM:SS | Часы:минуты:секунды | 00:30:00 — каждые 30 минут |
Nd HH:MM:SS | Дни + время | 7d 00:00:00 — каждые 7 дней |
0 или пусто | Одноразовая задача | Выполняется один раз |
Примеры комбинированных интервалов:
[admin@MikroTik] ># Каждые 2 дня и 12 часов interval=2d 12:00:00 # Каждые 90 минут interval=01:30:00 # Каждые 7 дней (еженедельно) interval=7d 00:00:00
Примеры
Пример 1: Ежедневный backup конфигурации
Создаём резервную копию конфигурации каждый день в 02:00. Файл сохраняется на внутренний диск роутера.
[admin@MikroTik] ># Скрипт экспорта конфигурации /system/scheduler add name=daily-backup \ start-time=02:00:00 interval=1d \ on-event={ :local date [/system/clock/get date] :local fname ("backup-" . $date) /export file=$fname /system/backup/save name=$fname :log info "Backup created: $fname" } \ policy=read,write,ftp,sensitive \ comment="Daily config backup at 02:00"
Проверка созданных файлов:
[admin@MikroTik] >/file/print where name~"backup-"
Пример 2: Еженедельная перезагрузка
Перезагрузка роутера каждое воскресенье в 04:00 для очистки памяти и обновления состояния. Установите start-date на ближайшее воскресенье.
[admin@MikroTik] >/system/scheduler add name=weekly-reboot \ start-date=jan/05/2025 start-time=04:00:00 \ interval=7d \ on-event="/system/reboot" \ policy=read,reboot \ comment="Weekly reboot on Sunday 04:00"
Пример 3: Обновление DNS blacklist каждые 6 часов
Загрузка списка вредоносных доменов и импорт в static DNS.
[admin@MikroTik] >/system/scheduler add name=dns-blacklist-update \ start-time=00:00:00 interval=6h \ on-event={ :log info "DNS blacklist: starting update" /tool/fetch url="https://example.com/blacklist.rsc" \ dst-path=blacklist.rsc mode=https :delay 5s /import file-name=blacklist.rsc :log info "DNS blacklist: update complete" } \ policy=read,write,ftp,test \ comment="Update DNS blacklist every 6 hours"
Пример 4: Отправка отчёта в Telegram каждое утро
Отправка информации о состоянии роутера в Telegram-бот каждый день в 08:00.
[admin@MikroTik] ># Предварительно настройте переменные /system/script/environment add name=telegramBot value="123456:ABC-token" /system/script/environment add name=telegramChat value="-1001234567890" /system/scheduler add name=telegram-morning-report \ start-time=08:00:00 interval=1d \ on-event={ :local botToken [/system/script/environment get [find name=telegramBot] value] :local chatId [/system/script/environment get [find name=telegramChat] value] :local identity [/system/identity/get name] :local uptime [/system/resource/get uptime] :local cpu [/system/resource/get cpu-load] :local mem [/system/resource/get free-memory] :local totalMem [/system/resource/get total-memory] :local ver [/system/resource/get version] :local msg ("Router: $identity\nUptime: $uptime\nCPU: $cpu%\n" . \ "Free RAM: $mem / $totalMem\nRouterOS: $ver") :local url ("https://api.telegram.org/bot$botToken/sendMessage" . \ "\?chat_id=$chatId&text=$msg") /tool/fetch url=$url keep-result=no :log info "Telegram morning report sent" } \ policy=read,write,ftp,test,sensitive \ comment="Send morning status report to Telegram"
Пример 5: Включение/отключение Wi-Fi по расписанию
Два задания: включение Wi-Fi в 08:00 (начало рабочего дня) и отключение в 22:00 (ночь).
[admin@MikroTik] ># Включение Wi-Fi в 08:00 /system/scheduler add name=wifi-enable \ start-time=08:00:00 interval=1d \ on-event={ /interface/wifi/enable [find where disabled=yes and name~"wifi"] :log info "Wi-Fi enabled (working hours start)" } \ policy=read,write \ comment="Enable Wi-Fi at 08:00" # Отключение Wi-Fi в 22:00 /system/scheduler add name=wifi-disable \ start-time=22:00:00 interval=1d \ on-event={ /interface/wifi/disable [find where name~"wifi"] :log info "Wi-Fi disabled (night hours start)" } \ policy=read,write \ comment="Disable Wi-Fi at 22:00"
Пример 6: Очистка DNS кэша каждый час
Полезно при частой смене DNS-записей или при отладке.
[admin@MikroTik] >/system/scheduler add name=dns-cache-flush \ start-time=00:00:00 interval=1h \ on-event={ /ip/dns/cache/flush :log info "DNS cache flushed" } \ policy=read,write \ comment="Flush DNS cache every hour"
Пример 7: Проверка обновлений RouterOS раз в неделю
Проверка наличия обновлений и запись результата в лог.
[admin@MikroTik] >/system/scheduler add name=check-updates \ start-time=09:00:00 interval=7d \ on-event={ /system/package/update/check-for-updates :delay 10s :local installed [/system/package/update/get installed-version] :local latest [/system/package/update/get latest-version] :if ($installed != $latest) do={ :log warning "RouterOS update available: $installed -> $latest" } else={ :log info "RouterOS is up to date: $installed" } } \ policy=read,write,policy \ comment="Check for RouterOS updates weekly"
Пример 8: Ротация логов
Экспорт лога в файл каждую неделю с очисткой файлового хранилища от старых backup.
[admin@MikroTik] >/system/scheduler add name=log-rotation \ start-time=Sunday,00:00:00 interval=7d \ on-event={ :local date [/system/clock/get date] /log/print file=("log-" . $date) # Удаление файлов логов старше 4 недель (вручную или через проверку) :foreach f in=[/file/find where name~"log-" and type="script"] do={ :local fname [/file/get $f name] :log info "Log archived: $fname" } :log info "Log rotation complete" } \ policy=read,write,ftp \ comment="Weekly log rotation"
Пример 9: Мониторинг uptime — уведомление о перезагрузке
При каждой загрузке роутера скрипт отправляет уведомление (через email или Telegram), что произошла перезагрузка.
[admin@MikroTik] >/system/scheduler add name=reboot-notification \ start-time=startup interval=0 \ on-event={ :delay 30s :local identity [/system/identity/get name] :local time [/system/clock/get time] :local date [/system/clock/get date] :local reason "Router $identity rebooted at $date $time" :log warning $reason # Email-уведомление (предварительно настройте /tool/e-mail) /tool/e-mail/send to="admin@example.com" \ subject="[MikroTik] $identity - REBOOT" \ body=$reason } \ policy=read,write,ftp,test,sensitive \ comment="Send notification on router reboot"
Задержка :delay 30s нужна, чтобы дождаться инициализации интерфейсов и получения IP-адреса перед отправкой email.
Пример 10: Динамическое обновление IP через DDNS
Обновление IP-адреса на DDNS-сервисе (например, DynDNS или No-IP) каждые 5 минут.
[admin@MikroTik] >/system/scheduler add name=ddns-update \ start-time=startup interval=5m \ on-event={ :local wanInterface "ether1" :local ddnsUser "myuser" :local ddnsPass "mypassword" :local ddnsHost "myhost.ddns.net" :local currentIP [/ip/address/get [find interface=$wanInterface] address] # Убираем маску подсети из адреса :set currentIP [:pick $currentIP 0 [:find $currentIP "/"]] :local url ("https://$ddnsUser:$ddnsPass@dynupdate.no-ip.com/nic/update" . \ "\?hostname=$ddnsHost&myip=$currentIP") /tool/fetch url=$url keep-result=no :log info "DDNS updated: $ddnsHost -> $currentIP" } \ policy=read,write,ftp,test \ comment="Update DDNS every 5 minutes"
Scheduler и Script: когда что использовать
Inline on-event vs вызов /system/script
Scheduler позволяет писать код двумя способами: прямо в поле on-event (inline) или вызывать сохранённый скрипт.
| Критерий | Inline on-event | Вызов скрипта |
|---|---|---|
| Длина кода | До 5–10 строк | Любая длина |
| Повторное использование | Нет (только в этой задаче) | Да (можно вызывать из разных мест) |
| Редактирование | Нужно пересоздавать задачу | Редактируется отдельно |
| Отладка | Сложнее | Проще (можно запускать вручную) |
| Экспорт / бэкап | Включён в scheduler | Экспортируется отдельно |
Рекомендация: используйте inline для простых однострочных команд. Для сложных задач (более 5 строк, переменные, условия) создавайте скрипт в /system/script и вызывайте его из scheduler.
Вызов скрипта из scheduler
[admin@MikroTik] ># Создание скрипта /system/script add name=backup-script \ policy=read,write,ftp,sensitive \ source={ :local date [/system/clock/get date] /export file=("backup-" . $date) /system/backup/save name=("backup-" . $date) :log info "Backup complete" } # Вызов скрипта из scheduler /system/scheduler add name=daily-backup \ start-time=02:00:00 interval=1d \ on-event="/system/script/run backup-script" \ policy=read,write,ftp,sensitive \ comment="Run backup script daily"
Важно: policy в scheduler должен быть не меньше, чем policy в скрипте. Если скрипту нужен ftp, а в scheduler указан только read,write — скрипт завершится с ошибкой прав доступа.
Мониторинг и проверка
Просмотр всех задач
[admin@MikroTik] ># Полный список задач /system/scheduler print # Детальная информация с run-count и next-run /system/scheduler print detail # Только активные задачи (не disabled) /system/scheduler print where disabled=no # Поиск задач по имени /system/scheduler print where name~"backup"
Пример вывода print detail:
code0 name="daily-backup" on-event="/system/script/run backup-script" start-date=2025-01-01 start-time=02:00:00 interval=1d policy=read,write,ftp,sensitive run-count=45 next-run=jan/16/2025 02:00:00
Ручной запуск задачи
Для тестирования можно запустить задачу вручную, не дожидаясь расписания:
[admin@MikroTik] ># Запуск задачи по имени /system/scheduler/run-once [find name=daily-backup]
Либо выполните код on-event напрямую в terminal для отладки.
Проверка выполнения через логи
[admin@MikroTik] ># Все сообщения от скриптов /log/print where topics~"script" # Ошибки /log/print where topics~"error" # Последние 20 записей лога /log/print count=20
Мониторинг run-count
Если run-count не увеличивается — задача не выполняется. Возможные причины:
- Задача
disabled=yes - Время
next-runещё не наступило - Ошибка в
on-event— задача запускается, но падает с ошибкой - Проблемы с
policy
[admin@MikroTik] ># Проверка: задача активна? /system/scheduler print where name=daily-backup proplist=name,disabled,run-count,next-run
Безопасность
Принцип минимальных привилегий
Каждая задача должна иметь только те policy, которые ей действительно необходимы:
[admin@MikroTik] ># Плохо — избыточные права /system/scheduler add name=dns-flush interval=1h \ on-event="/ip/dns/cache/flush" \ policy=read,write,ftp,reboot,policy,test,password,sniff,sensitive,romon # Хорошо — минимальные права /system/scheduler add name=dns-flush interval=1h \ on-event="/ip/dns/cache/flush" \ policy=read,write
Защита credentials в on-event
Никогда не храните пароли и токены непосредственно в поле on-event:
[admin@MikroTik] ># Плохо — пароль виден в /export /system/scheduler add name=ddns interval=5m \ on-event={ :local pass "MySuperSecret123" /tool/fetch url="https://user:$pass@ddns.example.com/update" } # Хорошо — пароль в environment /system/script/environment add name=ddnsPassword value="MySuperSecret123" /system/scheduler add name=ddns interval=5m \ on-event={ :local pass [/system/script/environment get [find name=ddnsPassword] value] /tool/fetch url="https://user:$pass@ddns.example.com/update" } \ policy=read,write,ftp,test,sensitive
При /export скрипт в on-event экспортируется как текст, и пароли будут видны. Использование environment не решает проблему полностью (environment тоже экспортируется с sensitive), но разделяет логику и данные.
Аудит задач scheduler
Периодически проверяйте список задач — вредоносные скрипты могут добавить задачу в scheduler:
[admin@MikroTik] ># Полный аудит всех задач /system/scheduler print detail # Проверка: нет ли задач с policy=reboot, которые вы не создавали /system/scheduler print where policy~"reboot" # Проверка: нет ли задач с /tool/fetch (загрузка файлов) /system/scheduler print where on-event~"fetch"
Типичные ошибки
Ошибка 1: Недостаточные policy
Самая частая проблема — задача создана, но не выполняется, потому что не хватает прав.
Симптомы: run-count увеличивается, но действие не происходит. В логе — not enough permissions.
[admin@MikroTik] ># Ошибка: нет policy=ftp для записи файла /system/scheduler add name=backup interval=1d \ on-event="/export file=backup" \ policy=read,write # Исправление: добавляем ftp /system/scheduler set [find name=backup] policy=read,write,ftp
Ошибка 2: Синтаксическая ошибка в on-event
Если в поле on-event есть ошибка синтаксиса, задача будет запускаться, но код не выполнится — молча, без видимого уведомления в WinBox.
Симптомы: run-count увеличивается, но ожидаемого результата нет. Ошибка видна только в логе.
[admin@MikroTik] ># Ошибка: пропущена закрывающая кавычка /system/scheduler add name=test interval=1h \ on-event=":log info \"test started" # Исправление: правильные escape-кавычки /system/scheduler set [find name=test] \ on-event=":log info \"test started\""
Рекомендация: всегда тестируйте код из on-event в terminal перед добавлением в scheduler.
Ошибка 3: Timezone и NTP
Если на роутере не настроен NTP, системное время может быть неправильным, и задачи будут запускаться не вовремя.
[admin@MikroTik] ># Проверка текущего времени /system/clock/print # Настройка NTP-клиента /system/ntp/client set enabled=yes /system/ntp/client/servers add address=pool.ntp.org # Установка timezone /system/clock set time-zone-name=Europe/Moscow
Ошибка 4: Interval drift
Scheduler считает interval от момента start-time, а не от момента последнего выполнения. Если start-time был 02:00 и interval=1d, задача всегда будет запускаться в 02:00 (±1 секунда). Но если start-time был в прошлом и interval не делится ровно на сутки — время запуска может «плыть».
[admin@MikroTik] ># Пример drift: interval=25h, start-time=00:00 # День 1: 00:00 # День 2: 01:00 # День 3: 02:00 # ... # Через 24 дня: 00:00 (цикл)
Для задач, которые должны выполняться строго в определённое время каждый день, всегда используйте interval=1d или interval=24h.
Ошибка 5: Задача startup выполняется до инициализации сети
При start-time=startup код выполняется очень рано — интерфейсы могут быть ещё не инициализированы, DHCP-адрес ещё не получен.
[admin@MikroTik] ># Ошибка: отправка email при startup без задержки /system/scheduler add name=boot-notify start-time=startup \ on-event="/tool/e-mail/send to=\"admin@example.com\" subject=\"Reboot\" body=\"OK\"" # Исправление: добавляем задержку 30-60 секунд /system/scheduler add name=boot-notify start-time=startup \ on-event={ :delay 60s /tool/e-mail/send to="admin@example.com" subject="Reboot" body="OK" } \ policy=read,write,ftp,test
Ошибка 6: Дублирование задач
При повторном выполнении /system/scheduler add с тем же именем RouterOS создаёт вторую задачу (имена не уникальны на уровне БД). Это может привести к двойному выполнению.
[admin@MikroTik] ># Проверка дубликатов /system/scheduler print where name=daily-backup # Безопасное создание: удалить старую перед добавлением :if ([:len [/system/scheduler/find name=daily-backup]] > 0) do={ /system/scheduler/remove [find name=daily-backup] } /system/scheduler add name=daily-backup interval=1d \ on-event="/system/script/run backup-script" \ policy=read,write,ftp
Продвинутые сценарии
Имитация cron-расписания «каждый будний день»
RouterOS scheduler не поддерживает расписание по дням недели напрямую. Обходное решение — проверка дня недели внутри скрипта:
[admin@MikroTik] >/system/scheduler add name=weekday-task \ start-time=09:00:00 interval=1d \ on-event={ :local dayOfWeek [/system/clock/get time-zone-name] :local date [/system/clock/get date] # Получаем день недели через вычисление :local dow [:pick [/system/clock/get time] 0 0] # Альтернативный способ: проверка через :totime :local currentDay :set currentDay [/system/clock/get date] # Выполняем только по будням (Mon-Fri) # Проверяем, используя собственную функцию определения дня :log info "Weekday check: running daily task" # Здесь ваш код } \ policy=read,write
Более надёжный подход — создать 5 задач с interval=7d, каждая стартующая в свой будний день.
Цепочка задач
Иногда нужно выполнить несколько действий последовательно с задержками:
[admin@MikroTik] ># Задача 1: скачать файл /system/scheduler add name=chain-step1 \ start-time=03:00:00 interval=1d \ on-event={ /tool/fetch url="https://example.com/rules.rsc" dst-path=rules.rsc :delay 10s # Запуск следующего шага /system/script/run chain-step2 } \ policy=read,write,ftp,test # Скрипт для шага 2 /system/script add name=chain-step2 \ policy=read,write,ftp \ source={ /import file-name=rules.rsc :log info "Chain complete: rules imported" }
Scheduler + Netwatch
Комбинация scheduler и netwatch для сложных сценариев мониторинга:
[admin@MikroTik] ># Scheduler создаёт файл статуса каждые 5 минут /system/scheduler add name=health-check interval=5m \ on-event={ :local cpu [/system/resource/get cpu-load] :local mem [/system/resource/get free-memory] :local totalMem [/system/resource/get total-memory] :local memPercent (($totalMem - $mem) * 100 / $totalMem) :if ($cpu > 90 || $memPercent > 90) do={ :log error "HIGH LOAD: CPU=$cpu% MEM=$memPercent%" } } \ policy=read,write
Итоги
| Задача | Тип | Рекомендуемый interval |
|---|---|---|
| Backup конфигурации | Периодическая | 1d (ежедневно) |
| Перезагрузка | Периодическая | 7d (еженедельно) |
| DNS blacklist | Периодическая | 6h |
| Telegram-отчёт | Периодическая | 1d |
| Wi-Fi вкл/выкл | Периодическая | 1d (два задания) |
| DNS flush | Периодическая | 1h |
| Проверка обновлений | Периодическая | 7d |
| Ротация логов | Периодическая | 7d |
| Уведомление о перезагрузке | Startup | startup |
| DDNS обновление | Startup + периодическая | startup + 5m |
Scheduler — мощный инструмент автоматизации MikroTik, который при правильной настройке превращает роутер в полностью автономную систему. Ключевые правила: минимальные policy, тестирование кода перед добавлением в scheduler, настроенный NTP для точного времени и регулярный аудит задач для безопасности.
[Создание задачи]
│
▼
[RouterOS таймер — проверка каждую секунду]
│
├── Время не наступило → ожидание
│
└── Время наступило →
├── Проверка policy
├── Выполнение on-event
├── Обновление run-count
└── Расчёт next-run (если есть interval)
/system/scheduler add name=my-task interval=1d \
start-time=03:00:00 \
on-event="/export file=backup" \
policy=read,write,ftp,sensitive \
comment="Daily backup at 03:00"
# Каждые 6 часов, начиная с 00:00
/system/scheduler add name=every-6h \
start-time=00:00:00 interval=6h \
on-event=":log info \"Running every 6 hours\"" \
policy=read,write
# Одноразовая перезагрузка в 03:00 5 января 2025
/system/scheduler add name=one-time-reboot \
start-date=jan/05/2025 start-time=03:00:00 \
on-event="/system/reboot" \
policy=read,reboot
# Отправка уведомления при загрузке
/system/scheduler add name=on-boot-notify \
start-time=startup interval=0 \
on-event=":log warning \"Router rebooted at \$[/system/clock/get time]\"" \
policy=read,write
# Каждые 2 дня и 12 часов
interval=2d 12:00:00
# Каждые 90 минут
interval=01:30:00
# Каждые 7 дней (еженедельно)
interval=7d 00:00:00
# Скрипт экспорта конфигурации
/system/scheduler add name=daily-backup \
start-time=02:00:00 interval=1d \
on-event={
:local date [/system/clock/get date]
:local fname ("backup-" . $date)
/export file=$fname
/system/backup/save name=$fname
:log info "Backup created: $fname"
} \
policy=read,write,ftp,sensitive \
comment="Daily config backup at 02:00"
/file/print where name~"backup-"
/system/scheduler add name=weekly-reboot \
start-date=jan/05/2025 start-time=04:00:00 \
interval=7d \
on-event="/system/reboot" \
policy=read,reboot \
comment="Weekly reboot on Sunday 04:00"
/system/scheduler add name=dns-blacklist-update \
start-time=00:00:00 interval=6h \
on-event={
:log info "DNS blacklist: starting update"
/tool/fetch url="https://example.com/blacklist.rsc" \
dst-path=blacklist.rsc mode=https
:delay 5s
/import file-name=blacklist.rsc
:log info "DNS blacklist: update complete"
} \
policy=read,write,ftp,test \
comment="Update DNS blacklist every 6 hours"
# Предварительно настройте переменные
/system/script/environment add name=telegramBot value="123456:ABC-token"
/system/script/environment add name=telegramChat value="-1001234567890"
/system/scheduler add name=telegram-morning-report \
start-time=08:00:00 interval=1d \
on-event={
:local botToken [/system/script/environment get [find name=telegramBot] value]
:local chatId [/system/script/environment get [find name=telegramChat] value]
:local identity [/system/identity/get name]
:local uptime [/system/resource/get uptime]
:local cpu [/system/resource/get cpu-load]
:local mem [/system/resource/get free-memory]
:local totalMem [/system/resource/get total-memory]
:local ver [/system/resource/get version]
:local msg ("Router: $identity\nUptime: $uptime\nCPU: $cpu%\n" . \
"Free RAM: $mem / $totalMem\nRouterOS: $ver")
:local url ("https://api.telegram.org/bot$botToken/sendMessage" . \
"\?chat_id=$chatId&text=$msg")
/tool/fetch url=$url keep-result=no
:log info "Telegram morning report sent"
} \
policy=read,write,ftp,test,sensitive \
comment="Send morning status report to Telegram"
# Включение Wi-Fi в 08:00
/system/scheduler add name=wifi-enable \
start-time=08:00:00 interval=1d \
on-event={
/interface/wifi/enable [find where disabled=yes and name~"wifi"]
:log info "Wi-Fi enabled (working hours start)"
} \
policy=read,write \
comment="Enable Wi-Fi at 08:00"
# Отключение Wi-Fi в 22:00
/system/scheduler add name=wifi-disable \
start-time=22:00:00 interval=1d \
on-event={
/interface/wifi/disable [find where name~"wifi"]
:log info "Wi-Fi disabled (night hours start)"
} \
policy=read,write \
comment="Disable Wi-Fi at 22:00"
/system/scheduler add name=dns-cache-flush \
start-time=00:00:00 interval=1h \
on-event={
/ip/dns/cache/flush
:log info "DNS cache flushed"
} \
policy=read,write \
comment="Flush DNS cache every hour"
/system/scheduler add name=check-updates \
start-time=09:00:00 interval=7d \
on-event={
/system/package/update/check-for-updates
:delay 10s
:local installed [/system/package/update/get installed-version]
:local latest [/system/package/update/get latest-version]
:if ($installed != $latest) do={
:log warning "RouterOS update available: $installed -> $latest"
} else={
:log info "RouterOS is up to date: $installed"
}
} \
policy=read,write,policy \
comment="Check for RouterOS updates weekly"
/system/scheduler add name=log-rotation \
start-time=Sunday,00:00:00 interval=7d \
on-event={
:local date [/system/clock/get date]
/log/print file=("log-" . $date)
# Удаление файлов логов старше 4 недель (вручную или через проверку)
:foreach f in=[/file/find where name~"log-" and type="script"] do={
:local fname [/file/get $f name]
:log info "Log archived: $fname"
}
:log info "Log rotation complete"
} \
policy=read,write,ftp \
comment="Weekly log rotation"
/system/scheduler add name=reboot-notification \
start-time=startup interval=0 \
on-event={
:delay 30s
:local identity [/system/identity/get name]
:local time [/system/clock/get time]
:local date [/system/clock/get date]
:local reason "Router $identity rebooted at $date $time"
:log warning $reason
# Email-уведомление (предварительно настройте /tool/e-mail)
/tool/e-mail/send to="admin@example.com" \
subject="[MikroTik] $identity - REBOOT" \
body=$reason
} \
policy=read,write,ftp,test,sensitive \
comment="Send notification on router reboot"
/system/scheduler add name=ddns-update \
start-time=startup interval=5m \
on-event={
:local wanInterface "ether1"
:local ddnsUser "myuser"
:local ddnsPass "mypassword"
:local ddnsHost "myhost.ddns.net"
:local currentIP [/ip/address/get [find interface=$wanInterface] address]
# Убираем маску подсети из адреса
:set currentIP [:pick $currentIP 0 [:find $currentIP "/"]]
:local url ("https://$ddnsUser:$ddnsPass@dynupdate.no-ip.com/nic/update" . \
"\?hostname=$ddnsHost&myip=$currentIP")
/tool/fetch url=$url keep-result=no
:log info "DDNS updated: $ddnsHost -> $currentIP"
} \
policy=read,write,ftp,test \
comment="Update DDNS every 5 minutes"
# Создание скрипта
/system/script add name=backup-script \
policy=read,write,ftp,sensitive \
source={
:local date [/system/clock/get date]
/export file=("backup-" . $date)
/system/backup/save name=("backup-" . $date)
:log info "Backup complete"
}
# Вызов скрипта из scheduler
/system/scheduler add name=daily-backup \
start-time=02:00:00 interval=1d \
on-event="/system/script/run backup-script" \
policy=read,write,ftp,sensitive \
comment="Run backup script daily"
# Полный список задач
/system/scheduler print
# Детальная информация с run-count и next-run
/system/scheduler print detail
# Только активные задачи (не disabled)
/system/scheduler print where disabled=no
# Поиск задач по имени
/system/scheduler print where name~"backup"
0 name="daily-backup" on-event="/system/script/run backup-script"
start-date=2025-01-01 start-time=02:00:00 interval=1d
policy=read,write,ftp,sensitive run-count=45 next-run=jan/16/2025 02:00:00
# Запуск задачи по имени
/system/scheduler/run-once [find name=daily-backup]
# Все сообщения от скриптов
/log/print where topics~"script"
# Ошибки
/log/print where topics~"error"
# Последние 20 записей лога
/log/print count=20
# Проверка: задача активна?
/system/scheduler print where name=daily-backup proplist=name,disabled,run-count,next-run
# Плохо — избыточные права
/system/scheduler add name=dns-flush interval=1h \
on-event="/ip/dns/cache/flush" \
policy=read,write,ftp,reboot,policy,test,password,sniff,sensitive,romon
# Хорошо — минимальные права
/system/scheduler add name=dns-flush interval=1h \
on-event="/ip/dns/cache/flush" \
policy=read,write
# Плохо — пароль виден в /export
/system/scheduler add name=ddns interval=5m \
on-event={
:local pass "MySuperSecret123"
/tool/fetch url="https://user:$pass@ddns.example.com/update"
}
# Хорошо — пароль в environment
/system/script/environment add name=ddnsPassword value="MySuperSecret123"
/system/scheduler add name=ddns interval=5m \
on-event={
:local pass [/system/script/environment get [find name=ddnsPassword] value]
/tool/fetch url="https://user:$pass@ddns.example.com/update"
} \
policy=read,write,ftp,test,sensitive
# Полный аудит всех задач
/system/scheduler print detail
# Проверка: нет ли задач с policy=reboot, которые вы не создавали
/system/scheduler print where policy~"reboot"
# Проверка: нет ли задач с /tool/fetch (загрузка файлов)
/system/scheduler print where on-event~"fetch"
# Ошибка: нет policy=ftp для записи файла
/system/scheduler add name=backup interval=1d \
on-event="/export file=backup" \
policy=read,write
# Исправление: добавляем ftp
/system/scheduler set [find name=backup] policy=read,write,ftp
# Ошибка: пропущена закрывающая кавычка
/system/scheduler add name=test interval=1h \
on-event=":log info \"test started"
# Исправление: правильные escape-кавычки
/system/scheduler set [find name=test] \
on-event=":log info \"test started\""
# Проверка текущего времени
/system/clock/print
# Настройка NTP-клиента
/system/ntp/client set enabled=yes
/system/ntp/client/servers add address=pool.ntp.org
# Установка timezone
/system/clock set time-zone-name=Europe/Moscow
# Пример drift: interval=25h, start-time=00:00
# День 1: 00:00
# День 2: 01:00
# День 3: 02:00
# ...
# Через 24 дня: 00:00 (цикл)
# Ошибка: отправка email при startup без задержки
/system/scheduler add name=boot-notify start-time=startup \
on-event="/tool/e-mail/send to=\"admin@example.com\" subject=\"Reboot\" body=\"OK\""
# Исправление: добавляем задержку 30-60 секунд
/system/scheduler add name=boot-notify start-time=startup \
on-event={
:delay 60s
/tool/e-mail/send to="admin@example.com" subject="Reboot" body="OK"
} \
policy=read,write,ftp,test
# Проверка дубликатов
/system/scheduler print where name=daily-backup
# Безопасное создание: удалить старую перед добавлением
:if ([:len [/system/scheduler/find name=daily-backup]] > 0) do={
/system/scheduler/remove [find name=daily-backup]
}
/system/scheduler add name=daily-backup interval=1d \
on-event="/system/script/run backup-script" \
policy=read,write,ftp
/system/scheduler add name=weekday-task \
start-time=09:00:00 interval=1d \
on-event={
:local dayOfWeek [/system/clock/get time-zone-name]
:local date [/system/clock/get date]
# Получаем день недели через вычисление
:local dow [:pick [/system/clock/get time] 0 0]
# Альтернативный способ: проверка через :totime
:local currentDay
:set currentDay [/system/clock/get date]
# Выполняем только по будням (Mon-Fri)
# Проверяем, используя собственную функцию определения дня
:log info "Weekday check: running daily task"
# Здесь ваш код
} \
policy=read,write
# Задача 1: скачать файл
/system/scheduler add name=chain-step1 \
start-time=03:00:00 interval=1d \
on-event={
/tool/fetch url="https://example.com/rules.rsc" dst-path=rules.rsc
:delay 10s
# Запуск следующего шага
/system/script/run chain-step2
} \
policy=read,write,ftp,test
# Скрипт для шага 2
/system/script add name=chain-step2 \
policy=read,write,ftp \
source={
/import file-name=rules.rsc
:log info "Chain complete: rules imported"
}
# Scheduler создаёт файл статуса каждые 5 минут
/system/scheduler add name=health-check interval=5m \
on-event={
:local cpu [/system/resource/get cpu-load]
:local mem [/system/resource/get free-memory]
:local totalMem [/system/resource/get total-memory]
:local memPercent (($totalMem - $mem) * 100 / $totalMem)
:if ($cpu > 90 || $memPercent > 90) do={
:log error "HIGH LOAD: CPU=$cpu% MEM=$memPercent%"
}
} \
policy=read,write