Инструменты пользователя

Инструменты сайта


mikrotik:rb951ui-2nd:routeros:tools:netwatch

Оповещение о восстановлении Интернет-соединения на MikroTik

Прошел тут у нас недавно во Владивостоке ледяной дождь. Небывалых масштабов и разрушений! И, конечно же, пропал Интернет! Вовсе! Надолго!

Первый день я иногда подключался к роутеру и смотрел, а не появился ли он, искомый. Во второй день уже что-то поднадоело! А на третий день появились эти скрипты. 8-) В итоге, через 5 дней мне на почту свалилось уведомление, что Интернет есть и можно расслабиться.

В отличии от полноценного фэйловера, в данном случае я решил использовать утилиту «Netwatch» из пакета «Advanced Tools» – во-первых, для разнообразия, а, во-вторых, чтобы не нагружать периодическим выполнением скриптов и так не очень мощный маршрутизатор «hAP».

:!: Другой вариант проверки доступности с использованием LibreNMS, описан тут.

Логика работы

Утилита «Netwatch» периодически проверяет связь с указанным хостом и, если она пропадает, один раз выполняет инструкции из раздела «Down», а когда появляется – один раз из раздела «Up».

Эти разделы ссылаются на соответствующие скрипты, которые:

  • при падении связи запоминают дату и время;
  • при восстановлении – отправляют письмо со временем падения и восстановления.

При реализации этого же, но только через скрипты, пришлось бы еще писать счетчик, который подавлял бы выдачу постоянных уведомлений, а так, это не нужно.

Важное замечание

В принципе, в разделах «Up» и «Donw» можно расположить сами скрипты, но! У «Netwatch» есть две проблемы1):

  1. Он не может нормально оперировать глобальными переменными, из-за чего приходится использовать файл для хранения значений. Для этого нужна политика «ftp».
  2. Он строго ограничен четырьмя политиками – «read,write,test,reboot», а нам нужна еще и «ftp»!

Поэтому приходится размещать тексты скриптов отдельно и во всех обязательно включать «Don't Require Permissions»!

Комментарии к коду

Вся эта затея сводится к настройке «Netwatch» и добавлению двух2) скриптов.

netwatch

Тут все просто – что пингуем3), с какой периодичностью и названия наших скриптов. Таймаут по умолчанию 1000 мс, но я поставил 300 и это нормально работает.

host=8.8.8.8
interval=00:01:00
timeout=300ms
down-script=internet-down
up-script=internet-up

internet-down

Вводим переменные для работы преобразователя даты в нормальную.

:local monthToNum;
:local dateToPick;
:local dateToLog;
:local timeToLog;

Текст, выводящийся в логах, когда Интернет падает.

:local errorTxt "Netwatch определил, что нет Интернета!";

Получаем и преобразовываем дату в нормальный вид. Получаем время.

:set monthToNum {jan="01";feb="02";mar="03";apr="04";may="05";jun="06";jul="07";aug="08";sep="09";oct="10";nov="11";dec="12";};
:set dateToPick [/system clock get date];
:set dateToLog ( [:pick $dateToPick 4 6] . "." . ( $monthToNum -> [:pick $dateToPick 0 3] ) . "." . [:pick $dateToPick 7 11] );
:set timeToLog [/system clock get time];

Пишем в файл дату и время. Если файла нет, создаем его и опять таки пишем в него дату и время. Задержка нужна обязательно, т.к. иначе файл не успевает создаться и… все плохо.

/file {
  :do { set lastInternetStaus.txt contents="$dateToLog $timeToLog";
  } on-error={
    /system routerboard print file="lastInternetStaus";
    :delay 2s;
    set lastInternetStaus.txt contents="$dateToLog $timeToLog";
  }
}

Пишем в лог ошибку о том, что нет Интернета.

:log error ("$errorTxt");

internet-up

Электронный адрес того, кого будем оповещать.

:local myEmail "nikolay@soloshin.su";

Объявляем необходимые переменные.

:local internetStatus;

Поучаем и преобразовываем дату. Получаем время.

:local monthToNum;
:local dateToPick;
:local dateToLog;
:local timeToLog;

:set monthToNum {jan="01";feb="02";mar="03";apr="04";may="05";jun="06";jul="07";aug="08";sep="09";oct="10";nov="11";dec="12";};
:set dateToPick [/system clock get date];
:set dateToLog ( [:pick $dateToPick 4 6] . "." . ( $monthToNum -> [:pick $dateToPick 0 3] ) . "." . [:pick $dateToPick 7 11] );
:set timeToLog [/system clock get time];

Получаем в переменную «internetStatus» значение из файла, если его нет, создаем его и устанавливаем в значение «none», т.е. нет даты и времени предыдущего отключения Интернета – это нужно, т.к. при запуске или перезагрузке устройства «Netwatch» сразу же проверяет соединение с хостом. По сути, это бонус, позволяющий отслеживать незапланированные перезагрузки роутера.

/file {
  :do { :set internetStatus [ get lastInternetStaus.txt contents ];
  } on-error={
    /system routerboard print file="lastInternetStaus";
    :delay 2s;
    set lastInternetStaus.txt contents="none";
    :set internetStatus "none";
  }
}

Вводим всякие разные тексты.

:local mySubj "Состояние подключения к Интернету ($dateToLog $timeToLog)";
:local myMsg "Доступ к сети Интернет восстановлен в $dateToLog $timeToLog!\r\n\r\nДоступа не было с $internetStatus.";
:local errorTxt "невозможно отправить e-mail для Netwatch";

Отправляем письмо, если ошибка, пишем в лог.

:do { /tool e-mail send to=$myEmail subject=$mySubj body=$myMsg; } on-error={ :log error ("$errorTxt"); }

Сбрасываем значение в файле.

/file set lastInternetStaus.txt contents="none";

Код для импорта

Разработано для RouterOS v6.45.1, проверено на v6.47.8.

netwatch-scripts.rsc
/tool netwatch
add down-script=internet-down host=8.8.8.8 timeout=300ms up-script=\
    internet-up interval=00:01:00
/system script
add dont-require-permissions=yes name=internet-down owner=vasya policy=\
    ftp,read,write source="# Written by Nikolay Soloshin (nikolay@soloshin.su)\
    \_for RouterOS v6.45.1 on hAP (mipsbe) @ 2020.11\r\
    \n\r\
    \n:local monthToNum;\r\
    \n:local dateToPick;\r\
    \n:local dateToLog;\r\
    \n:local timeToLog;\r\
    \n\r\
    \n:local errorTxt \"Netwatch \EE\EF\F0\E5\E4\E5\EB\E8\EB, \F7\F2\EE \ED\E5\
    \F2 \C8\ED\F2\E5\F0\ED\E5\F2\E0!\";\r\
    \n\r\
    \n:set monthToNum {jan=\"01\";feb=\"02\";mar=\"03\";apr=\"04\";may=\"05\";\
    jun=\"06\";jul=\"07\";aug=\"08\";sep=\"09\";oct=\"10\";nov=\"11\";dec=\"12\
    \";};\r\
    \n:set dateToPick [/system clock get date];\r\
    \n:set dateToLog ( [:pick \$dateToPick 4 6] . \".\" . ( \$monthToNum -> [:\
    pick \$dateToPick 0 3] ) . \".\" . [:pick \$dateToPick 7 11] );\r\
    \n:set timeToLog [/system clock get time];\r\
    \n\r\
    \n/file {\r\
    \n  :do { set lastInternetStaus.txt contents=\"\$dateToLog \$timeToLog\";\
    \r\
    \n  } on-error={\r\
    \n    /system routerboard print file=\"lastInternetStaus\";\r\
    \n    :delay 2s;\r\
    \n    set lastInternetStaus.txt contents=\"\$dateToLog \$timeToLog\";\r\
    \n  }\r\
    \n}\r\
    \n\r\
    \n:log error (\"\$errorTxt\");\r\
    \n\r\
    \n# With love from Vladivostok."
add dont-require-permissions=yes name=internet-up owner=vasya policy=\
    ftp,read,write,test source="# Written by Nikolay Soloshin (nikolay@soloshi\
    n.su) for RouterOS v6.45.1 on hAP (mipsbe) @ 2020.11\r\
    \n\r\
    \n:local myEmail \"nikolay@soloshin.su\";\r\
    \n\r\
    \n:local internetStatus;\r\
    \n\r\
    \n:local monthToNum;\r\
    \n:local dateToPick;\r\
    \n:local dateToLog;\r\
    \n:local timeToLog;\r\
    \n\r\
    \n:set monthToNum {jan=\"01\";feb=\"02\";mar=\"03\";apr=\"04\";may=\"05\";\
    jun=\"06\";jul=\"07\";aug=\"08\";sep=\"09\";oct=\"10\";nov=\"11\";dec=\"12\
    \";};\r\
    \n:set dateToPick [/system clock get date];\r\
    \n:set dateToLog ( [:pick \$dateToPick 4 6] . \".\" . ( \$monthToNum -> [:\
    pick \$dateToPick 0 3] ) . \".\" . [:pick \$dateToPick 7 11] );\r\
    \n:set timeToLog [/system clock get time];\r\
    \n\r\
    \n/file {\r\
    \n  :do { :set internetStatus [ get lastInternetStaus.txt contents ];\r\
    \n  } on-error={\r\
    \n    /system routerboard print file=\"lastInternetStaus\";\r\
    \n    :delay 2s;\r\
    \n    set lastInternetStaus.txt contents=\"none\";\r\
    \n    :set internetStatus \"none\";\r\
    \n  }\r\
    \n}\r\
    \n\r\
    \n:local mySubj \"\D1\EE\F1\F2\EE\FF\ED\E8\E5 \EF\EE\E4\EA\EB\FE\F7\E5\ED\
    \E8\FF \EA \C8\ED\F2\E5\F0\ED\E5\F2\F3 (\$dateToLog \$timeToLog)\";\r\
    \n:local myMsg \"\C4\EE\F1\F2\F3\EF \EA \F1\E5\F2\E8 \C8\ED\F2\E5\F0\ED\E5\
    \F2 \E2\EE\F1\F1\F2\E0\ED\EE\E2\EB\E5\ED \E2 \$dateToLog \$timeToLog!\\r\\\
    n\\r\\n\C4\EE\F1\F2\F3\EF\E0 \ED\E5 \E1\FB\EB\EE \F1 \$internetStatus.\";\
    \r\
    \n:local errorTxt \"\ED\E5\E2\EE\E7\EC\EE\E6\ED\EE \EE\F2\EF\F0\E0\E2\E8\
    \F2\FC e-mail \E4\EB\FF Netwatch\";\r\
    \n\r\
    \n:do { /tool e-mail send to=\$myEmail subject=\$mySubj body=\$myMsg; } on\
    -error={ :log error (\"\$errorTxt\"); }\r\
    \n\r\
    \n/file set lastInternetStaus.txt contents=\"none\";\r\
    \n\r\
    \n# With love from Vladivostok."

Политики запуска

Это минимально необходимый набор для работы скрипта.

internet-down internet-up
dont-require-permissions=yes
ftp
read
write
test

Дисклеймер

  • Использование материалов данной базы знаний разрешено на условиях лицензии, указанной внизу каждой страницы! При использовании материалов активная гиперссылка на соответствующую страницу данной базы знаний обязательна!
  • Автор не несет и не может нести какую либо ответственность за последствия использования материалов, размещенных в данной базе знаний. Все материалы предоставляются по принципу «как есть». Используйте их исключительно на свой страх и риск.
  • Все высказывания, мысли или идеи автора, размещенные в материалах данной базе знаний, являются исключительно его личным субъективным мнением и могут не совпадать с мнением читателей!
  • При размещении ссылок в данной базе знаний на интернет-страницы третьих лиц автор не несет ответственности за их техническую функциональность (особенно отсутствие вирусов) и содержание! При обнаружении таких ссылок, можно и желательно сообщить о них в комментариях к соответствующей статье.
1)
Подробнее в официальной wiki или на разных профильных форумах.
2)
Хотелось бы обойтись одним, но передача параметров, как, к примеру, здесь, тут, увы, невозможна!
3)
Я предпочитаю Google DNS, но, вероятно, лучше было бы указать что-то поближе к вашему провайдеру.

Обсуждение

Денис, 2023/01/27 19:35, 2023/01/27 20:15
Добрый день!

Вы сделали очень полезный скрипт, подскажите пожалуйста, как его дополнить, чтобы мне приходила еще информация о том, сколько времени отсутствовал интернет и сколько присутствовал?

$timeToLog-$internetStatus=Разница во времени (как получить это чило?)

Заранее спасибо!
Николай Солошин, 2023/01/27 20:25, 2023/01/27 20:26
Насколько я помню, Микротик возвращает дату-время только в текстовом формате в виде "mar/01/2009" и "20:24:58". В скрипте оно в таком виде и фигурирует, т.е. без дополнительного преобразования с ним работать (складывать, вычитать) невозможно.

Для решения вашей задачи, нужно искать в нете или самостоятельно писать функцию-костыль, которая будет переводить время в unix-формат. Далее все просто - вычитаем и переводим обратно у удобоваримый вид. )
Антон, 2023/07/31 19:00
Добрый день. На "семерке" 7.10.2 стал вместо даты подставлять: -0..-31 тут речь идет про 31.07.23..раньше все работало четко на 6ке. Видно что-то поменяли в новой прошивке.. не проверяли? у Вас работает на семерке?
Николай Солошин, 2023/07/31 19:35
Доброго!

Я этим скриптом уже не пользуюсь, полностью перешел на LibreNMS, поэтому не актуализировал его и не проверял на других релизах.

У меня самый свежий релиз, это 7.8. На нем, если построчно (полностью скрипт я там не гонял!) вводить в консоль часть кода с преобразованием даты, все работает штатно. В журналах изменений, на сайте MikroTik, с уровня моей версии и до 7.10 ничего об изменениях выдачи даты нет.

Вам нужно локализовать проблему, выяснив, на каком этапе происходит ошибка и потом конкретную строчку кода отладить в консоли.

Для диагностики, проще всего добавить в разных местах текста кода вывод значений переменных в лог (к примеру, ":log error $dateToLog").

Если проблему решите, поделитесь результатами, интересно. ))

p.s. Маловероятно, но попробуйте для начала выставить все политики запуска...
Антон, 2023/08/22 17:50
Салют, Николай.
Забыл отписаться.. проблема заключалась в том, что в новых прошивках переменная dateToPick [/system clock get date] получила другой формат.. в связи с этим нужно было подругому ее распарсить… так же отпала необходимость в переменной monthToNum
:set dateToLog ( [:pick $dateToPick 8 11] . "." . [:pick $dateToPick 5 7] . "." . [:pick $dateToPick 0 4] );
После этого все стало норм.
П.с. также заюзал LibreNMS.. все работает, но для моих задач данный функционал избыточен.. хотя было интересно попробывать. Оставил на виртуалке пусть крутится может руки дойдут расширю кругозор.
Николай Солошин, 2023/08/23 13:03
Понятно. Прекрасно, что разобрались! )) А с какой версии изменения? 7.8 точно еще по старому...

По LibreNMS у меня есть ворох статеек, вдруг пригодится. ))))
Ваш комментарий:
V᠎ O H I X O G S T K N K Y A Q E
 
Последнее изменение: 2023/03/25 01:03 — Николай Солошин