Прошел тут у нас недавно во Владивостоке ледяной дождь. Небывалых масштабов и разрушений! И, конечно же, пропал Интернет! Вовсе! Надолго!
Первый день я иногда подключался к роутеру и смотрел, а не появился ли он, искомый. Во второй день уже что-то поднадоело! А на третий день появились эти скрипты. В итоге, через 5 дней мне на почту свалилось уведомление, что Интернет есть и можно расслабиться.
В отличии от полноценного фэйловера, в данном случае я решил использовать утилиту Netwatch
из пакета Advanced Tools
– во-первых, для разнообразия, а, во-вторых, чтобы не нагружать периодическим выполнением скриптов и так не очень мощный маршрутизатор hAP
.
Утилита Netwatch
периодически проверяет связь с указанным хостом и, если она пропадает, один раз выполняет инструкции из раздела Down
, а когда появляется – один раз из раздела Up
.
Эти разделы ссылаются на соответствующие скрипты, которые:
При реализации этого же, но только через скрипты, пришлось бы еще писать счетчик, который подавлял бы выдачу постоянных уведомлений, а так, это не нужно.
В принципе, в разделах Up
и Donw
можно расположить сами скрипты, но! У Netwatch
есть две проблемы1):
ftp
.read,write,test,reboot
, а нам нужна еще и ftp
!
Поэтому приходится размещать тексты скриптов отдельно и во всех обязательно включать 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-формат. Далее все просто - вычитаем и переводим обратно у удобоваримый вид. )