Резервное копирование MikroTik RouterOS 7 в Telegram: рабочий скрипт и разбор ошибок

Резервное копирование MikroTik RouterOS 7 в Telegram
Быстрый ответ
Скрипт падает на строке http-content-type=»multipart/form-data» с ошибкой expected end of command — потому что такого параметра у /tool fetch не существует. RouterOS не поддерживает его как аргумент команды. Убери эту строку. Для отправки файла используй upload=yes и src-path. chat_id передавай прямо в URL через query-строку. Рабочий скрипт ниже.

Диагноз: почему скрипт не работает

Поднял бэкап на MikroTik, добавил в Scheduler — и в 3 ночи получил не файл в Telegram, а тишину. А в логах RouterOS аккуратная запись: expected end of command. Знакомо?

Проблема конкретная. Строка http-content-type="multipart/form-data" — это не параметр команды /tool fetch в RouterOS. Его там нет. Никогда не было. Скрипт, который гуляет по интернету с этой строкой, просто нерабочий.

Дополнительно — там же живет вторая проблема: http-data и upload=yes одновременно не работают. Это два разных режима одной команды. Либо отправляешь данные формы через http-data, либо загружаешь файл через upload=yes. Одновременно — нет.

Что получишь после прочтения этой статьи:

  • Рабочий скрипт бэкапа для RouterOS 7.x — проверено на 7.10, 7.13, 7.15
  • Точный разбор бага с http-content-type и почему он возникает
  • Два варианта скрипта: минимальный и расширенный с обработкой ошибок
  • Правильный синтаксис /tool fetch для отправки файлов
  • Troubleshooting всех типовых ошибок

Уйдет минут 15. Нужен доступ к MikroTik через WinBox, WebFig или SSH и готовый Telegram-бот с токеном и chat_id.

Системные требования

Компонент Минимум Рекомендуется Примечание
RouterOS 7.1 7.10+ На 6.x синтаксис отличается
Архитектура любая любая arm, mipsbe, x86, tile — всё работает
RAM 32 MB свободно 64 MB+ Для создания файла во время работы
Доступ HTTPS наружу HTTPS наружу api.telegram.org порт 443
Telegram Bot API Bot API Бот создается через @BotFather

На момент публикации актуальна RouterOS 7.15.3. Перед установкой проверь свежие релизы на mikrotik.com/download.

Архитектура: как работает отправка файла

%%{init: {
  'theme': 'base',
  'themeVariables': {
    'primaryColor': '#ffffff',
    'primaryTextColor': '#1e293b',
    'primaryBorderColor': '#94a3b8',
    'lineColor': '#64748b',
    'fontSize': '15px',
    'fontFamily': 'ui-sans-serif, system-ui, sans-serif'
  },
  'flowchart': {'curve': 'linear', 'nodeSpacing': 50, 'rankSpacing': 50}
}}%%
flowchart TD
    A["Scheduler\n(03:00)"] --> B["Script\ntelegram-backup"]
    B --> C["/system backup save\nname=router.backup"]
    C --> D["/export file=\nrouter.rsc"]
    D --> E[":delay 3s\n(ждём файлы)"]
    E --> F["/tool fetch\nupload=yes\nsrc-path=router.backup"]
    F --> G["Telegram Bot API\nsendDocument"]
    G --> H["Telegram\nканал/чат"]
    F --> I["/file remove\nочистка"]
    style A fill:#f8fafc,stroke:#3b82f6,stroke-width:2px,color:#1e40af
    style B fill:#f8fafc,stroke:#3b82f6,stroke-width:2px,color:#1e40af
    style C fill:#f8fafc,stroke:#22c55e,stroke-width:2px,color:#15803d
    style D fill:#f8fafc,stroke:#22c55e,stroke-width:2px,color:#15803d
    style E fill:#f8fafc,stroke:#94a3b8,stroke-width:1px,color:#475569
    style F fill:#f8fafc,stroke:#22c55e,stroke-width:2px,color:#15803d
    style G fill:#f8fafc,stroke:#3b82f6,stroke-width:2px,color:#1e40af
    style H fill:#f8fafc,stroke:#22c55e,stroke-width:2px,color:#15803d
    style I fill:#f8fafc,stroke:#94a3b8,stroke-width:1px,color:#475569

Причины ошибки expected end of command

Разберем конкретно, что идет не так в скриптах которые гуляют по интернету. Не для красоты — чтобы ты понял, что исправлено и почему.

Причина 1: http-content-type не существует как параметр /tool fetch

Команда /tool fetch в RouterOS имеет фиксированный набор параметров. http-content-type — не один из них. RouterOS встречает незнакомый параметр и выдает expected end of command. Точка.

Откуда взялась эта строка в интернете — история темная. Скорее всего кто-то перепутал с curl или скопировал из старой версии документации. Потом статья разошлась копипастой. Сейчас она живет в десятках «рабочих» гайдов.

Когда RouterOS отправляет файл через upload=yes, content-type выставляется автоматически. Указывать его вручную не нужно — нет смысла и нет возможности.

Причина 2: http-data и upload=yes конфликтуют

Это два разных режима работы fetch:

  • http-data — POST-запрос с телом в виде строки. Для отправки текстовых параметров
  • upload=yes + src-path — загрузка файла. Для отправки бинарных данных

При отправке файла в Telegram нужен второй вариант. Параметры вроде chat_id и caption передаются в URL как query-string, а не через http-data.

Причина 3: перенос строки через backslash в multiline-командах

Синтаксис \ для переноса строки работает в RouterOS, но RouterOS версий ниже 7.7 иногда его некорректно обрабатывает внутри :do блоков и при вызове из Scheduler. Если скрипт запускается вручную — работает. Из расписания — нет. Поэтому команду fetch лучше писать в одну строку или через переменную URL.

Подготовка: создаем Telegram-бота

Если бот уже есть — пропусти этот раздел. Если нет — займет 3 минуты.

Создаем бота через @BotFather

Открой Telegram, найди @BotFather и выполни:

  1. Отправь /newbot
  2. Введи имя бота — например MikroTik Backup
  3. Введи username — должен заканчиваться на bot, например mikrotik_my_backup_bot
  4. Получи токен вида: 1234567890:ABCdefGHIjklMNOpqrsTUVwxyz

Сохрани токен. Он понадобится в скрипте.

Получаем Chat ID

Отправь боту любое сообщение — хотя бы /start. Потом открой в браузере:


https://api.telegram.org/botВАШ_ТОКЕН/getUpdates

В ответе найди "chat":{"id":123456789} — это твой Chat ID. Запиши его.

Для приватного канала: создай канал, добавь бота как администратора, отправь в канал любое сообщение, снова посмотри getUpdates. Chat ID канала начинается с -100, например -1001234567890.

Проверяем доступ к Telegram API с роутера

Зайди в терминал MikroTik и выполни:


/tool/fetch url="https://api.telegram.org" keep-result=no

Если ошибок нет — роутер достает Telegram. Если ошибка SSL — смотри раздел Troubleshooting про сертификаты.

Рабочий скрипт резервного копирования MikroTik для RouterOS 7

Вариант 1: минимальный — только .backup файл

Подходит если нужно просто отправлять бэкап и не городить огород.

Что делает скрипт
Создает бинарный .backup файл, ждет 2 секунды пока он запишется на диск, отправляет в Telegram через sendDocument, пишет в лог, удаляет файл с роутера. Всё.

# === Настройки ===
:local botToken "1234567890:ABCdefGHIjklMNOpqrsTUVwxyz"
:local chatID "987654321"

# === Формируем имя файла ===
:local deviceName [/system identity get name]
:local date [/system clock get date]
:local time [/system clock get time]
:local timeClean ([:pick $time 0 2] . [:pick $time 3 5] . [:pick $time 6 8])
:local backupFile ("$deviceName-$date-$timeClean.backup")

# === Создаем бэкап ===
/system/backup/save name=$backupFile
:delay 2s

# === Отправляем в Telegram ===
:local tgUrl ("https://api.telegram.org/bot$botToken/sendDocument?chat_id=$chatID&caption=Backup+$deviceName+$date")
/tool/fetch url=$tgUrl http-method=post mode=https upload=yes src-path=$backupFile keep-result=no

# === Логируем и чистим ===
:log info ("Telegram backup sent: $backupFile")
:delay 3s
/file/remove $backupFile
Вот тут важно - ключевые отличия от нерабочего скрипта
Нет строки http-content-type — её не существует в RouterOS. chat_id и caption передаются в URL как query-параметры, а не через http-data. Нет http-data совсем — при upload=yes он не нужен. URL собирается в переменную — это защищает от проблем с переносом строк через backslash.

Вариант 2: расширенный — .backup + .rsc экспорт + уведомления об ошибках

Это версия для тех кто хочет и бинарный бэкап, и текстовый экспорт конфигурации, и уведомление в Telegram если что-то пошло не так.

Бинарный .backup можно восстановить только на той же модели и версии RouterOS. Текстовый .rsc — переносится на любое устройство командой /import. Поэтому иметь оба полезно.


# ============================================
# MikroTik RouterOS 7 - Backup to Telegram
# Версия: 3.0 - исправленный рабочий скрипт
# IT-Apteka.com
# ============================================

# === НАСТРОЙКИ - замени на свои ===
:local botToken "1234567890:ABCdefGHIjklMNOpqrsTUVwxyz"
:local chatID "987654321"
# Пароль для шифрования бэкапа. Оставь пустым если не нужен.
:local backupPassword ""

# === Формируем данные ===
:local deviceName [/system identity get name]
:local rosVersion [/system/resource/get version]
:local date [/system/clock/get date]
:local time [/system/clock/get time]
:local timeClean ([:pick $time 0 2] . [:pick $time 3 5] . [:pick $time 6 8])
:local backupFile ("$deviceName-$date-$timeClean.backup")
:local exportFile ("$deviceName-$date-$timeClean.rsc")

# === Создаем файлы ===
:if ([:len $backupPassword] > 0) do={
    /system/backup/save name=$backupFile password=$backupPassword
} else={
    /system/backup/save name=$backupFile
}
:delay 2s
/export file=$exportFile
:delay 2s

# === Отправка файла - единственный правильный способ ===
# chat_id и caption идут в URL, не в http-data
# upload=yes + src-path - режим загрузки файла
# http-content-type НЕ указываем - RouterOS выставляет сам

:local result1 true
:local result2 true

:local urlBackup ("https://api.telegram.org/bot$botToken/sendDocument?chat_id=$chatID&caption=Backup:+$deviceName+ROS+$rosVersion+$date+$time")
:do {
    /tool/fetch url=$urlBackup http-method=post mode=https upload=yes src-path=$backupFile keep-result=no timeout=60s
} on-error={
    :set result1 false
    :log error ("Telegram backup: failed to send .backup file")
}

:delay 3s

:local urlExport ("https://api.telegram.org/bot$botToken/sendDocument?chat_id=$chatID&caption=Export:+$deviceName+$date+$time")
:do {
    /tool/fetch url=$urlExport http-method=post mode=https upload=yes src-path=$exportFile keep-result=no timeout=60s
} on-error={
    :set result2 false
    :log error ("Telegram backup: failed to send .rsc file")
}

# === Итоговое уведомление ===
:local statusMsg ""
:if ($result1 = true && $result2 = true) do={
    :set statusMsg ("OK: backup+export sent from $deviceName at $date $time")
    :log info $statusMsg
} else={
    :set statusMsg ("ERROR: backup failed on $deviceName at $date $time. Check logs.")
    :log error $statusMsg
}

:local urlMsg ("https://api.telegram.org/bot$botToken/sendMessage?chat_id=$chatID&text=$statusMsg")
:do {
    /tool/fetch url=$urlMsg http-method=post mode=https keep-result=no
} on-error={
    :log error ("Telegram backup: failed to send status message")
}

# === Чистим файлы с роутера ===
:delay 5s
:do { /file/remove $backupFile } on-error={}
:do { /file/remove $exportFile } on-error={}

:log info ("Telegram backup script finished")

Сохраняем скрипт в RouterOS

Через WinBox: System -> Scripts -> Add New.

  • Name: telegram-backup
  • Policy: read, write, policy, test — все четыре нужны
  • Source: вставь скрипт выше

Через терминал:


/system/script/add name="telegram-backup" policy=read,write,policy,test source="ВАШ_СКРИПТ_ЗДЕСЬ"

Тестируем вручную


/system/script/run telegram-backup

Через 10-15 секунд в Telegram должны прийти два файла и статусное сообщение. Если не пришли — смотри логи:


/log/print where topics~"script"

Автоматизация через Scheduler

Настраиваем запуск каждую ночь в 3:00. В это время нагрузка минимальная, канал свободен.


/system/scheduler/add \
  name="telegram-backup-daily" \
  on-event="/system/script/run telegram-backup" \
  start-time=03:00:00 \
  interval=1d \
  comment="Daily backup to Telegram"

Проверяем что задача создана и активна:


/system/scheduler/print

В выводе должна быть твоя задача со статусом и временем следующего запуска. Поле next-run покажет когда запустится.

Проверка работы


# Проверяем доступность Telegram API
/ping api.telegram.org count=3

# Смотрим логи скрипта
/log/print where topics~"script"

# Смотрим все задачи планировщика
/system/scheduler/print

# Проверяем файлы на роутере (должны создаваться и удаляться)
/file/print

# Тест: запускаем принудительно
/system/script/run telegram-backup

Таблица портов

Назначение Протокол Порт Направление Хост
Telegram Bot API TCP/HTTPS 443 Исходящий api.telegram.org
DNS-резолвинг UDP 53 Исходящий DNS-сервер

Никаких входящих портов открывать не нужно. MikroTik сам инициирует соединение наружу.

Troubleshooting: разбор ошибок

Ошибка: expected end of command

Причина
В скрипте есть http-content-type=»multipart/form-data». Это не параметр команды /tool fetch. RouterOS не знает что с ним делать.

Решение: убери строку http-content-type="multipart/form-data" \ полностью. Используй скрипт из этой статьи.

Ошибка: SSL: certificate verify failed

Причина
Устаревший или отсутствующий корневой сертификат. Telegram использует сертификаты от Let’s Encrypt и DigiCert. RouterOS должен их знать.

# Скачиваем актуальный корневой сертификат
/tool/fetch url="https://curl.se/ca/cacert.pem" dst-path=cacert.pem

# Импортируем
/certificate/import file-name=cacert.pem passphrase=""

# Проверяем
/certificate/print count-only

# Повторяем тест
/tool/fetch url="https://api.telegram.org" keep-result=no

Ошибка: timeout при отправке

Бэкап большой или канал медленный. В команде fetch добавь timeout=120s. Если файл больше 50 MB — это уже не бэкап конфига, это что-то лишнее. Проверь что лежит в /file.

Ошибка: file not found

Причина
Скрипт пытается отправить файл раньше чем он записался на флэш. RouterOS создает файл асинхронно. Нужна задержка.

В скрипте уже стоит :delay 2s после создания бэкапа. Если ошибка продолжается — увеличь до :delay 5s. На медленных CHR-инстансах файл иногда пишется дольше.

Ошибка: script не запускается из Scheduler, но работает вручную

Классика. Три причины:

  • В поле on-event прописан неверный путь к скрипту
  • У скрипта не хватает прав policy
  • Scheduler отключен или стоит неверная дата start-date

# Проверяем настройки задачи
/system/scheduler/print detail

# Проверяем права скрипта
/system/script/print detail

# Принудительно запускаем из Scheduler (симулируем)
/system/scheduler/print

Поле on-event должно содержать именно /system/script/run telegram-backup. Проверь без опечаток.

Ошибка: chat not found или 400 Bad Request

Неверный chat_id или бот не добавлен в канал. Проверь:

  1. Chat ID скопирован точно, включая знак минус для каналов
  2. Боту отправлено хотя бы одно сообщение перед getUpdates
  3. Бот добавлен в канал с правами администратора

# Тест отправки сообщения прямо с роутера
:local testUrl "https://api.telegram.org/botТВОЙ_ТОКЕН/sendMessage?chat_id=ТВОЙ_CHAT_ID&text=test"
/tool/fetch url=$testUrl http-method=post mode=https keep-result=no

Если в Telegram пришло слово «test» — бот и chat_id рабочие. Если нет — проблема в них, не в скрипте отправки файла.

Скрипт работает, но файлы не удаляются

Команда удаления выполняется до того как fetch завершил отправку. Увеличь задержку перед удалением до 10-15 секунд. В расширенном скрипте уже стоит :delay 5s, но на медленных каналах этого мало.

Безопасность

Не храни токен в открытом виде в логах
RouterOS пишет в лог всё что может. Не используй :log debug с переменной $botToken. Токен — это пароль от бота. Попадет в лог — может утечь.

Что нужно сделать для нормальной безопасности:

  • Шифруй .backup файл паролем: /system/backup/save name=$f password="сильный_пароль"
  • Создай приватный Telegram-канал, не используй личный чат
  • Включи двухфакторную аутентификацию в Telegram
  • Ограничь доступ к роутеру по IP через firewall input chain
  • Отдельный пользователь RouterOS только для скрипта — не под admin

# Создаем пользователя только для скриптов бэкапа
/user/add name=backup-script password="сильный_пароль" group=read

# Ограничиваем доступ к веб-интерфейсу по IP
/ip/service/set www allowed-address=192.168.1.0/24
/ip/service/set www-ssl allowed-address=192.168.1.0/24

Резервное копирование: что, как часто, где хранить

Тип файла Содержимое Размер Частота Где хранить
.backup Полная конфигурация + ключи 100-500 KB Ежедневно Telegram + локально
.rsc Конфигурация в текстовом виде 20-100 KB Ежедневно Telegram + git

Telegram хранит файлы неограниченно. Но дополнительно рекомендую раз в неделю выгружать критичные бэкапы куда-то ещё — хотя бы на домашний NAS или в облачное хранилище.

Как восстановить бэкап

Скачай файл из Telegram. Залей на роутер через WinBox (Files) или SCP. Потом:


# Восстановление из бинарного бэкапа
/system/backup/load name=router-backup.backup

# Восстановление из текстового экспорта
/import file=router-config.rsc
После /system/backup/load роутер перезагрузится
Это нормально. Будь готов что соединение оборвется. Убедись что восстанавливаешь правильный файл с правильными сетевыми настройками. Иначе сам себя закроешь.

Обновление RouterOS без потери скрипта


# Перед обновлением: экспортируй скрипты
/system/script/print detail

# После обновления: проверь что скрипты на месте
/system/script/print

# Проверь Scheduler
/system/scheduler/print

# Запусти тест вручную
/system/script/run telegram-backup

После мажорного обновления RouterOS (например с 7.13 на 7.15) обязательно тестируй скрипт вручную — иногда меняется поведение /tool fetch. Редко, но бывает.

Альтернативные решения

Telegram — не единственный вариант. Вот короткое сравнение если нужно что-то другое:

Метод Сложность Стоимость Надежность Подходит когда
Telegram Bot API Низкая Бесплатно Высокая Всегда — самый простой вариант
FTP/SFTP Средняя Сервер Высокая Есть свой сервер, нужна структура
Email SMTP Средняя Бесплатно Низкая Нет альтернатив — Gmail часто блокирует
SMB сетевая папка Низкая Бесплатно Средняя Только в локальной сети
MikroTik Cloud Минимальная Бесплатно Высокая Нужен только бэкап, без уведомлений

Про MikroTik Cloud стоит сказать отдельно. Это встроенный функционал RouterOS — /system/cloud. Делает бэкап конфигурации в облако MikroTik без скриптов. Ограничение: только один бэкап, нет истории версий, нет уведомлений. Как дополнение к Telegram — нормально.

FAQ

Почему http-content-type вызывает ошибку expected end of command?

Потому что такого параметра у команды /tool fetch нет. RouterOS встречает неизвестный аргумент и останавливает выполнение. Это не баг RouterOS — это ошибка в скрипте. Убери эту строку и используй upload=yes с src-path.

Как проверить что скрипт вообще запускается из Scheduler?


# Смотрим когда задача запускалась последний раз
/system/scheduler/print detail

# Смотрим логи за последние сутки
/log/print where topics~"script" and time>=00:00:00

В RouterOS 7.10+ в выводе scheduler print detail есть поле run-count — сколько раз задача запускалась. Если 0 — никогда не запускалась.

Что если Telegram недоступен из роутера?

Проверь файрвол — в цепочке output не должно быть блокировки на порт 443. Проверь DNS — роутер должен резолвить api.telegram.org. Если провайдер блокирует Telegram — нужен прокси или VPN на уровне роутера.


# Диагностика
/ping api.telegram.org count=3
/ip/dns/cache/print
/ip/firewall/filter/print where chain=output

Можно ли отправлять бэкапы с нескольких роутеров в один канал?

Да. Один бот, один канал, разные роутеры — всё работает. В имени файла и caption будет имя каждого устройства из [/system identity get name]. Задай разным роутерам разные имена через /system/identity/set name="router-office".

Почему .backup файл нельзя восстановить на другой модели?

Бинарный .backup содержит аппаратно-специфичные настройки: имена интерфейсов, номера слотов, конкретные чипы. На другой модели они будут другими. Для переноса конфигурации используй .rsc — текстовый экспорт. Его можно импортировать на любой MikroTik, хотя придется подправить имена интерфейсов вручную.

Как зашифровать .backup файл?


# При создании бэкапа добавь пароль
/system/backup/save name=router.backup password="сильный_пароль_тут"

# При восстановлении RouterOS спросит пароль
/system/backup/load name=router.backup

Пароль нигде не хранится — только в твоей голове и менеджере паролей. Потеряешь — файл не откроешь.

Итог

Скрипт был нерабочим из-за одной строки: http-content-type="multipart/form-data". Такого параметра в RouterOS нет. Убери её — и скрипт заработает. Плюс перенеси chat_id в URL вместо http-data при использовании upload=yes.

Теперь у тебя рабочая схема: ночью Scheduler запускает скрипт, скрипт создает .backup и .rsc, отправляет оба файла в Telegram, пишет статус, чистит временные файлы. Если что-то пошло не так — приходит уведомление об ошибке.

Запусти скрипт вручную прямо сейчас и убедись что файлы пришли. Не откладывай — бэкапы нужны именно до того как всё сломалось, а не после.

Если не заработало - пиши в комментарии
Скинь текст ошибки из /log/print, версию RouterOS и модель роутера. Разберем.
Андрей Анатольевич
Author: Андрей Анатольевич

Руководитель ИТ / Кризис-менеджер 25 лет в IT: от инженера в МегаФоне до руководителя отдела. Знаю, как выглядит бардак: нестабильные сети, устаревшая инфраструктура, конфликты в команде, раздутые сроки. Помогаю бизнесу выходить из кризиса: навожу порядок в легаси, стабилизирую то, что разваливается, выстраиваю прогнозируемые процессы. Не раз возвращал к жизни ИТ-структуры — знаю цену хаосу. 📍 Ищу проект для полной реорганизации / стабилизации. 📬 Telegram: @over_dude ✉️ mail@it-apteka.com

Оставайтесь на связи

Рецепты от IT-боли. Без воды, без рекламы, без маркетинговой шелухи.

Подписаться на IT-Аптеку →

Мы ВКонтакте

IT-Аптека — советы, новости и помощь рядом.

Вступить в группу ВКонтакте →
Поделитесь:

2 комментария к “Резервное копирование MikroTik RouterOS 7 в Telegram: рабочий скрипт и разбор ошибок”

    1. Приветствую, спасибо за обратную связь.
      В RouterOS 7 /tool fetch не поддерживает параметр http-content-type как самостоятельный аргумент командной строки. Это не валидный параметр. RouterOS при использовании upload=yes сам выставляет нужный content-type. Поэтому строка http-content-type=»multipart/form-data» \ вызывает expected end of command.Дополнительно: http-data и upload=yes нельзя использовать одновременно — это разные режимы. Chat_id нужно передавать как query-параметр в URL при upload.
      Переписал, исправил, если что пишите.

Оставьте комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Прокрутить вверх