Прошел тут у нас недавно во Владивостоке ледяной дождь. Небывалых масштабов и разрушений! И, конечно же, пропал Интернет! Вовсе! Надолго!
Первый день я иногда подключался к роутеру и смотрел, а не появился ли он, искомый. Во второй день уже что-то поднадоело! А на третий день появились эти скрипты. В итоге, через 5 дней мне на почту свалилось уведомление, что Интернет есть и можно расслабиться.
В отличии от полноценного фэйловера, в данном случае я решил использовать утилиту «Netwatch» из пакета «Advanced Tools» – во-первых, для разнообразия, а, во-вторых, чтобы не нагружать периодическим выполнением скриптов и так не очень мощный маршрутизатор «hAP».
Другой вариант проверки доступности с использованием LibreNMS, описан тут.
Утилита «Netwatch» периодически проверяет связь с указанным хостом и, если она пропадает, один раз выполняет инструкции из раздела «Down», а когда появляется – один раз из раздела «Up».
Эти разделы ссылаются на соответствующие скрипты, которые:
При реализации этого же, но только через скрипты, пришлось бы еще писать счетчик, который подавлял бы выдачу постоянных уведомлений, а так, это не нужно.
В принципе, в разделах «Up» и «Donw» можно расположить сами скрипты, но! У «Netwatch» есть две проблемы1):
Поэтому приходится размещать тексты скриптов отдельно и во всех обязательно включать «Don't Require Permissions»!
Вся эта затея сводится к настройке «Netwatch» и добавлению двух2) скриптов.
Тут все просто – что пингуем3), с какой периодичностью и названия наших скриптов. Таймаут по умолчанию 1000 мс, но я поставил 300 и это нормально работает.
host=8.8.8.8 interval=00:01:00 timeout=300ms down-script=internet-down up-script=internet-up
Вводим переменные для работы преобразователя даты в нормальную.
: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");
Электронный адрес того, кого будем оповещать.
: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.
/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 |
Обсуждение
Вы сделали очень полезный скрипт, подскажите пожалуйста, как его дополнить, чтобы мне приходила еще информация о том, сколько времени отсутствовал интернет и сколько присутствовал?
$timeToLog-$internetStatus=Разница во времени (как получить это чило?)
Заранее спасибо!
Для решения вашей задачи, нужно искать в нете или самостоятельно писать функцию-костыль, которая будет переводить время в unix-формат. Далее все просто - вычитаем и переводим обратно у удобоваримый вид. )
Я этим скриптом уже не пользуюсь, полностью перешел на LibreNMS, поэтому не актуализировал его и не проверял на других релизах.
У меня самый свежий релиз, это 7.8. На нем, если построчно (полностью скрипт я там не гонял!) вводить в консоль часть кода с преобразованием даты, все работает штатно. В журналах изменений, на сайте MikroTik, с уровня моей версии и до 7.10 ничего об изменениях выдачи даты нет.
Вам нужно локализовать проблему, выяснив, на каком этапе происходит ошибка и потом конкретную строчку кода отладить в консоли.
Для диагностики, проще всего добавить в разных местах текста кода вывод значений переменных в лог (к примеру, ":log error $dateToLog").
Если проблему решите, поделитесь результатами, интересно. ))
p.s. Маловероятно, но попробуйте для начала выставить все политики запуска...
Забыл отписаться.. проблема заключалась в том, что в новых прошивках переменная dateToPick [/system clock get date] получила другой формат.. в связи с этим нужно было подругому ее распарсить… так же отпала необходимость в переменной monthToNum
:set dateToLog ( [:pick $dateToPick 8 11] . "." . [:pick $dateToPick 5 7] . "." . [:pick $dateToPick 0 4] );
После этого все стало норм.
П.с. также заюзал LibreNMS.. все работает, но для моих задач данный функционал избыточен.. хотя было интересно попробывать. Оставил на виртуалке пусть крутится может руки дойдут расширю кругозор.
По LibreNMS у меня есть ворох статеек, вдруг пригодится. ))))