mikrotik-wiki.ru
Главная
Загрузка...

Планировщик задач на MikroTik — /system/scheduler

RouterOS 7.xSystem16 мин430 мар. 2026 г.
TelegramVK

Планировщик задач 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 сохраняет её в конфигурацию. Внутренний таймер каждую секунду проверяет, наступило ли время выполнения. Когда время наступает:

  1. RouterOS проверяет policy задачи — хватает ли прав
  2. Выполняет код из поля on-event в контексте виртуального пользователя с указанными policy
  3. Увеличивает счётчик run-count на 1
  4. Рассчитывает next-run на основе interval
  5. Если interval не задан — задача остаётся, но больше не выполняется (одноразовая)
code
[Создание задачи]
       │
       ▼
[RouterOS таймер — проверка каждую секунду]
       │
       ├── Время не наступило → ожидание
       │
       └── Время наступило →
              ├── Проверка policy
              ├── Выполнение on-event
              ├── Обновление run-count
              └── Расчёт next-run (если есть interval)

Scheduler vs cron: сравнение

КритерийMikroTik SchedulerLinux cron
Формат расписанияinterval (1h, 1d, 00:05:00)cron-выражение (*/5 * * * *)
Запуск «каждый понедельник в 8:00»start-date (Mon) + interval=7d0 8 * * 1
Запуск при старте системыstart-time=startup@reboot
Минимальный интервал1 секунда1 минута
Управление правамиpolicy (ftp, read, write...)пользователь crontab
Логирование:log + /log/printsyslog / journald
Зависимость от NTPДа (для start-date/start-time)Да
РедактированиеCLI / WinBox / WebFigcrontab -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:

ПараметрТипПо умолчаниюОписание
namestring(обязательный)Уникальное имя задачи
on-eventstring(обязательный)Команда или имя скрипта для выполнения
start-datedateтекущая датаДата первого запуска (jan/01/2025)
start-timetime / startupтекущее времяВремя первого запуска или startup
intervaltime00:00:00 (одноразовая)Интервал повторения
policylistread,write,policy,testПрава выполнения (через запятую)
disabledyes/nonoОтключить задачу без удаления
commentstring(пусто)Описание задачи

Параметр policy — права выполнения

Policy определяет, какие команды может выполнять задача. Это критически важный параметр безопасности:

PolicyОписаниеКогда нужен
readЧтение конфигурацииПочти всегда
writeИзменение конфигурацииДобавление/удаление правил, маршрутов
ftpДоступ к файловой системеBackup, запись файлов, /tool/fetch
rebootПерезагрузка и выключение/system/reboot
policyУправление пользователямиИзменение паролей, создание пользователей
testЗапуск тестовых утилитPing, traceroute, bandwidth-test
passwordИзменение своего пароляРедко используется в скриптах
sniffPacket 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

ФорматЗначениеПример
NsN секунд30s — каждые 30 секунд
NmN минут5m — каждые 5 минут
NhN часов6h — каждые 6 часов
NdN дней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:

code
 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

Ручной запуск задачи

Для тестирования можно запустить задачу вручную, не дожидаясь расписания:

[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 не увеличивается — задача не выполняется. Возможные причины:

  1. Задача disabled=yes
  2. Время next-run ещё не наступило
  3. Ошибка в on-event — задача запускается, но падает с ошибкой
  4. Проблемы с 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
Уведомление о перезагрузкеStartupstartup
DDNS обновлениеStartup + периодическаяstartup + 5m

Scheduler — мощный инструмент автоматизации MikroTik, который при правильной настройке превращает роутер в полностью автономную систему. Ключевые правила: минимальные policy, тестирование кода перед добавлением в scheduler, настроенный NTP для точного времени и регулярный аудит задач для безопасности.

[admin@MikroTik] >
[Создание задачи]
       │
       ▼
[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
System / Планировщик задач на MikroTik — /system/scheduler