Самый важный, я бы даже сказал, что основополагающий скрипт, т.к. без его загрузки при запуске устройства, другие скрипты не будут работать.
Им инициализируются:
Используется для тестирования. Если его раскомментировать, скрипт отработает на 50 секунд быстрее, но не будут инициализированы SMS и не будет проиграна музыка запуска.
# :local varOnly "yes";
Необходимо, чтобы скрипт не глючил при загрузке устройства, а устройство в свою очередь могло спокойно прогрузиться.
:if ( $varOnly != "yes" ) do={ :log info ("script will be executed after 50 seconds"); :delay 50s; }
Настройки для работы SMS. Предварительно, конечно, нужно настроить.
:global modemPort [/tool sms get port]; :global smsChannel [/tool sms get channel]; :global smsNumber [/tool sms get allowed-number];
Устанавливаем номер PPP подключения модема. Обычно 0
, но у всех по своему. Узнать можно введя в терминале /interface ppp-client print where name~«NAME»
, заменив NAME
на название подключения.
:global pppNumber 0;
Находим названия для наших Интернет-каналов. Будут использоваться для логирования, SMS и E-mail в других скриптах. Можно указать вручную, но… зачем? Смотрите номер физического интерфейса и пишете его вместо ether1
или ether2
.
:global ether1Name [/interface ethernet get [find default-name="ether1"] name]; :global ether2Name [/interface ethernet get [find default-name="ether2"] name];
Электронный адрес администратора для уведомлений.
:global adminEmail "name@domain.zone";
Список рассылки для уведомления сотрудников о состоянии Интернет-канала.
:global eventEmail "list@domain.zone";
Адреса для тестирования наличия Интернета на каналах. Шлюзы указывать нельзя! Лучшее решение, это DNS от Google.
:global pingTo1 "8.8.8.8"; :global pingTo2 "77.88.8.8";
Количество эхо-запросов по умолчанию.
:global pingCount 4;
Минимальное количество эхо-ответов, чтобы считать канал рабочим. Должно быть меньше, чем pingCount * 2.
В оригинальном фэйловер-скрипте использовались проценты, но в актуальной версии RouterOS нет дробей, увы. И на поиски этой ошибки я потратил огромное количество времени, пока не догадался поиграться в консоли с математическими операторами…
:global stableConnectFrom 6;
Частота отправки сообщения о неработающем резервном канале.
К примеру, чтобы оповещение отправлялось не чаще одного раза в 6 часов, при запуске задачи каждые 3 минуты, нужно указать 120.
:global setFailCounter 60;
Сброс состояния выполнения скрипта фэйловера, которое остается, к примеру, при сбросе питания во время выполения.
:global failoverRun false;
:global sendEvent do={
Чтобы проверить надежный режим, закомментируйте глобальную функцию modemPort и раскомментируйте локальную.
:global modemPort; # :local modemPort fake;
Инициализация переменных. errorTxt
, это текст сообщения об ошибке, выводимого в лог, если не удалось отправить сообщение в режиме $mode
(о них ниже).
:global smsChannel; :global smsNumber; :global adminEmail; :local errorTxt "Function \"sendEvent\" could not send $mode message!"; :local localTo; :local localSubj;
Выбор режима работы в зависимости от переданных функции переменных.
:if ( [ :typeof $to ] = "nothing" ) do={ :set localTo $adminEmail; } else={ :set localTo $to; } :if ( [ :typeof $subj ] = "nothing" ) do={ :local dateTime ([/system clock get date]."@".[/system clock get time]); :set localSubj "SMS transmission failed $dateTime!"; } else={ :set localSubj $subj; }
Надежный режим заключается в попытке сперва отправить SMS, а если не удалось (к примеру, модем повис), то отправить электронное письмо.
:if ( [ :typeof $mode ] = "nothing" || $mode = "safe" ) do={ :do { /tool sms send $modemPort channel=$smsChannel "$smsNumber" message=$msg; } on-error={ /tool e-mail send to=$localTo subject=$localSubj body=$msg; } }
Отправляем только SMS, если ошибка, то пишем в лог и больше ничего не делаем.
:if ( $mode = "sms" ) do={ :do { /tool sms send $modemPort channel=$smsChannel "$smsNumber" message=$msg; } on-error={ :log error ("$errorTxt"); } }
Отправляем только Email, если ошибка, то пишем в лог и больше ничего не делаем.
:if ( $mode = "mail" ) do={ :do { /tool e-mail send to=$localTo subject=$localSubj body=$msg; } on-error={ :log error ("$errorTxt"); } } }
Квадратные скобки указывают на необязательность соответствующих переменных или значений, а круглые скобки указывают на выбор одного из вариантов.
# [:(local|global) $anyVarMail "address@domain.zone";] # [:(local|global) $anyVarSubj "Any subject";] # [:(local|global) $anyVarMsg "Any message";] # $sendEvent [mode=(sms|mail|safe)] [to=(address@domain.zone|$anyVarMail)] [subj=("any subj"|$anyVarSubj)] msg=("any msg"|$anyVarMsg);
Обязательной является только одна переменная, msg
, - в этом случае будет использован надежный режим, адрес и тема по умолчанию.
mode
может принимать одно из трех значений - sms
, mail
или safe
.to
может быть взято из другой переменной или указано явно «address@domain.zone
».subj
так же может быть передано другой переменной или быть указано простым текстом в кавычках.:global pingSession do={
Инициализация переменных.
:global pingTo1; :global pingTo2; :global pingCount; :local localCount; :local localPingStatus;
Выбор режима работы в зависимости от переданных функции переменных.
:if ( [ :typeof $myPingCount ] = "nothing" ) do={ :set localCount $pingCount; } else={ :set localCount $myPingCount; }
Собственно, ядро функции - пигнует, запоминает, складывает. Все.
:do { :set localPingStatus \ ( [/ping $pingTo1 interface=$pingFrom count=$localCount] + \ [/ping $pingTo2 interface=$pingFrom count=$localCount] ); } on-error={}
Возвращает скрипту, вызвавшему эту функцию, результат.
:return $localPingStatus; }
Инициализируем обязательные переменные.
$intName
- название интерфейса с которого будем пинговать.pingStatus
- переменная в которую запишем результат.# :local $intName "Any-Interface-Name"; # :local pingStatus;
Вызываем функцию в стандартном режиме.
# :set pingStatus [ $pingSession pingFrom=$intName; ];
Или с указанием через переменную myPingCount
своего значения количества отправляемых эхо-запросов.
# :set pingStatus [ $pingSession pingFrom=$intName myPingCount=8; ];
При возвращении всех пакетов результат будет 16, т.к. производятся две попытки по 8 запросов.
Вывод предыдущей функции может быть передан этой функции для сохранения результатов проверки на диске устройства.
Для работы требуется политика ftp!
:global ispLogging do={
Инициализация переменных.
:global stableConnectFrom; :global runLogCount; :global logFileNum; :local contentsFile; :local fileName; :local monthToNum; :local dateToPick; :local dateToLog; :local timeToLog; :local warnLevel;
Проверка указания обязательной переменной outInt
. Если ее нет, то выходим с ошибкой.
:if ( [ :typeof $outInt ] = "nil" || [ :typeof $outInt ] = "nothing" ) do={ :local noInt "The variable \"outInt\" is missing, the function ends."; :log error ("$noInt"); :error "$noInt"; }
Получаем, преобразуем и записываем в переменные текущую дату и время.
: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];
Если переменная с указанием текущего номера файла имеет тип nothing
, что нормально после перезагрузки, преобразуем ее в массив.
:if ( [ :typeof $logFileNum ] = "nothing" ) do={ :set logFileNum [ :toarray "" ]; }
Заполняем эту переменную из файла. Если файла нет, создаем его и устанавливаем счетчик в 0
.
/file { :if ( [ :typeof ( $logFileNum -> "$outInt" ) ] = "nothing" ) do={ :do { :set ( $logFileNum -> "$outInt" ) [ get "isp-stat/counters/$outInt.txt" contents ]; } on-error={ /system routerboard print file="isp-stat/counters/$outInt"; :delay 2s; set "isp-stat/counters/$outInt.txt" contents="0"; :set ( $logFileNum -> "$outInt" ) [ get "isp-stat/counters/$outInt.txt" contents ]; } }
Если переменная с указанием текущего количества запусков имеет тип nothing
, что нормально после перезагрузки, преобразуем ее в массив.
:if ( [ :typeof $runLogCount ] = "nothing" ) do={ :set runLogCount [ :toarray "" ]; }
Накручиваем счетчик количества запуска функции. Если он больше 66
(65 строк в файле, потом файл становится сильно большим и система начинает глючить) обнуляем этот счетчик, накручиваем logFileNum
и пишем в соответствующий файл.
:if ( ( $runLogCount -> "$outInt" ) = "66" || [ :typeof ( $runLogCount -> "$outInt" ) ] = "nothing" ) do={ :set ( $runLogCount -> "$outInt" ) 0; :set ( $logFileNum -> "$outInt" ) ( ( $logFileNum -> "$outInt" ) + 1 ); :do { set "isp-stat/counters/$outInt.txt" contents=( $logFileNum -> "$outInt" ); } on-error={ /system routerboard print file="isp-stat/counters/$outInt"; :delay 2s; set "isp-stat/counters/$outInt.txt" contents=( $logFileNum -> "$outInt" ); } } else={ :set ( $runLogCount -> "$outInt" ) (( $runLogCount -> "$outInt" ) + 1 ); } }
Проверяем частоту создания нового файла (ежедневно или ежемесячно) и пишем в переменную название текущего файла. Если переменная newFileAt
не была передана выходим с ошибкой.
:if ( $newFileAt = "month" ) do={ :set fileName ( $outInt . "-" . [:pick $dateToPick 7 11] . "." . \ ( $monthToNum -> [:pick $dateToPick 0 3] ) . "-" . ( $logFileNum -> "$outInt" ) ); } else={ :if ( $newFileAt = "day" ) do={ :set fileName ( $outInt . "-" . [:pick $dateToPick 7 11] . "." . \ ( $monthToNum -> [:pick $dateToPick 0 3] ) . "." . [:pick $dateToPick 4 6] . "-" . \ ( $logFileNum -> "$outInt" ) ); } else={ :local noFile "The variable \"newFileAt\" is missing, the function ends."; :log error ("$noFile"); :error "$noFile"; } }
Проверяем насколько удачным было тестирование канала, если плохо, ставим пометку.
:if ( $receivedPing < $stableConnectFrom ) do={ :set warnLevel "!"; }
Читаем из файла данные, добавляем с новой строки новые и пишем все обратно. Если ошибка, создаем файл.
/file { :do { :set contentsFile [ get "isp-stat/$fileName.txt" contents ]; } on-error={ /system routerboard print file="isp-stat/$fileName"; :delay 2s; set "isp-stat/$fileName.txt" contents="Interface;Warning;Date;Time;Received;Total;Level;Mode"; :set contentsFile [ get "isp-stat/$fileName.txt" contents ]; } set "isp-stat/$fileName.txt" \ contents="$contentsFile\r\n$outInt;$warnLevel;$dateToLog;$timeToLog;$receivedPing;$totalPing;$stableConnectFrom;$startMode"; } }
Квадратные скобки указывают на необязательность соответствующих переменных или значений, а круглые скобки указывают на выбор одного из вариантов.
# $ ispLogging outInt=("InterfaceName"|$ether1) [receivedPing=($rPing|integer)] [totalPing=($tPing|integer)] [startMode=(script|sms|manual|"any-text")] newFileAt=(day|month);
Переменные outInt
и newFileAt
являются обязательными.
Interface;Warning;Date;Time;Received;Total;Level;Mode In-MTS-0;;01.09.2020;09:09:28;8;8;6;test-modem-scheduler In-MTS-0;;01.09.2020;21:09:29;6;8;6;test-modem-scheduler In-MTS-0;;02.09.2020;09:09:28;8;8;6;test-modem-scheduler In-MTS-0;;02.09.2020;21:09:28;8;8;6;test-modem-scheduler In-MTS-0;;03.09.2020;09:09:28;8;8;6;test-modem-scheduler
Если переменная в начале скрипта раскомментирована, просто пишем в лог об этом и отправляем Email. В противном случае включаем прием SMS и сразу отправляем тестовую. Если ошибка, то пишем об этом Email.
:if ( $varOnly = "yes" ) do={ :local varOnlySubj "SMS reception is off!"; :local varOnlyMsg "Initialization script has been executed, but the SMS reception enable section is off!"; $sendEvent mode=mail subj=$varOnlySubj msg=$varOnlyMsg; :log warning ("$varOnlyMsg"); } else={ /tool sms set receive-enabled=yes; :delay 10s; :local smsOn "MikroTik rebooted! (send \":cmd 31337 script help\" for help)"; :local smsOnLog "SMS reception enabled!"; :local smsErrSubj "SMS transmission failed!"; :local smsErr "The device is rebooted, but the SMS notification could not be sent."; :local smsErrLog "Failed to enable SMS reception after reboot!"; :do { /tool sms send $modemPort channel=$smsChannel "$smsNumber" message=$smsOn; :log info ("$smsOnLog"); } on-error={ /tool e-mail send to=$localTo subject=$smsErrSubj body=$smsErr; :log warning ("$smsErrLog"); } :execute "startup-music"; }
Последней строчкой включаем победную музыку, оповещающую серверную об удачном старте.
/system script add comment="\C8\ED\E8\F6\E8\E0\EB\E8\E7\E0\F6\E8\FF \E3\EB\EE\E1\E0\EB\FC\ED\ \FB\F5 \EF\E5\F0\E5\EC\E5\ED\ED\FB\F5 \E8 SMS \EF\EE\F1\EB\E5 \EF\E5\F0\E5\ \E7\E0\E3\F0\F3\E7\EA\E8" dont-require-permissions=no name=\ variables-initialization owner=petya policy=\ read,write,policy,test,sensitive source="# Written by Nikolay Soloshin (ni\ kolay@soloshin.su) for RouterOS v6.46.3 on RB3011UiAS (arm) @ 2020.03\r\ \n\r\ \n# Uncomment to update variables without initializing and sending SMS\r\ \n# :local varOnly \"yes\";\r\ \n\r\ \n# Delay execution when the device boots.\r\ \n:if ( \$varOnly != \"yes\" ) do={\r\ \n :log info (\"script will be executed after 50 seconds\");\r\ \n :delay 50s;\r\ \n}\r\ \n\r\ \n#\r\ \n# Variables\r\ \n#\r\ \n\r\ \n# All values are taken from \"Tools\" -> \"SMS\"\r\ \n:global modemPort [/tool sms get port];\r\ \n:global smsChannel [/tool sms get channel];\r\ \n:global smsNumber [/tool sms get allowed-number];\r\ \n\r\ \n# Number PPP connection of modem (/interface ppp-client print where name\ ~\"MTS\")\r\ \n:global pppNumber 0;\r\ \n\r\ \n# Names of interfaces with Internet channels\r\ \n:global ether1Name [/interface ethernet get [find default-name=\"ether1\ \"] name];\r\ \n:global ether2Name [/interface ethernet get [find default-name=\"ether2\ \"] name];\r\ \n\r\ \n# Administrative email address for notification from scripts\r\ \n:global adminEmail \"csadmin@csdv.ru\";\r\ \n\r\ \n# Group email address for channel status notification from a script\r\ \n:global eventEmail \"internet-status@csdv.ru\";\r\ \n\r\ \n# Addresses for testing channels\r\ \n:global pingTo1 \"8.8.8.8\";\r\ \n:global pingTo2 \"77.88.8.8\";\r\ \n\r\ \n# The default number of echo requests to send.\r\ \n:global pingCount 4;\r\ \n\r\ \n# Minimum number of returned queries to consider the channel operational\ \_(should be less than pingCount * 2)\r\ \n:global stableConnectFrom 6;\r\ \n\r\ \n# The frequency of sending messages about the failure of the backup chan\ nel.\r\ \n# To send an alert no more than once every 6 hours when starting a task \ every 3 minutes, you need to specify 120.\r\ \n:global setFailCounter 60;\r\ \n\r\ \n# Reset script and function launch labels\r\ \n:global failoverRun false;\r\ \n\r\ \n#\r\ \n# Function for sending SMS and (or) letters from scripts (example below)\ \r\ \n#\r\ \n\r\ \n:global sendEvent do={\r\ \n\r\ \n# To check reliable mode, comment out the global function modemPort and \ uncomment the local\r\ \n :global modemPort;\r\ \n# :local modemPort ttt;\r\ \n\r\ \n :global smsChannel;\r\ \n :global smsNumber;\r\ \n :global adminEmail;\r\ \n\r\ \n :local errorTxt \"Function \\\"sendEvent\\\" could not send \$mode mes\ sage!\";\r\ \n\r\ \n :local localTo;\r\ \n :local localSubj;\r\ \n\r\ \n# Set the required variables if they are not passed to the function at s\ tartup\r\ \n :if ( [ :typeof \$to ] = \"nothing\" ) do={ :set localTo \$adminEmail;\ \_} else={ :set localTo \$to; }\r\ \n :if ( [ :typeof \$subj ] = \"nothing\" ) do={\r\ \n :local dateTime ([/system clock get date].\"@\".[/system clock get t\ ime]);\r\ \n :set localSubj \"SMS transmission failed \$dateTime!\";\r\ \n } else={ :set localSubj \$subj; }\r\ \n\r\ \n# Reliable mode - we try to send SMS, if it fails, we send mail\r\ \n :if ( [ :typeof \$mode ] = \"nothing\" || \$mode = \"safe\" ) do={\r\ \n :do {\r\ \n /tool sms send \$modemPort channel=\$smsChannel \"\$smsNumber\" me\ ssage=\$msg;\r\ \n } on-error={ /tool e-mail send to=\$localTo subject=\$localSubj bo\ dy=\$msg; }\r\ \n }\r\ \n\r\ \n# Mode - only SMS, if an error, do nothing else\r\ \n :if ( \$mode = \"sms\" ) do={\r\ \n :do { /tool sms send \$modemPort channel=\$smsChannel \"\$smsNumber\ \" message=\$msg; } on-error={ :log error (\"\$errorTxt\"); }\r\ \n }\r\ \n\r\ \n# Mode - only mail, if an error, do nothing else\r\ \n :if ( \$mode = \"mail\" ) do={\r\ \n :do { /tool e-mail send to=\$localTo subject=\$localSubj body=\$msg;\ \_} on-error={ :log error (\"\$errorTxt\"); }\r\ \n }\r\ \n}\r\ \n\r\ \n# Example (square brackets indicate the optionalness of the correspondin\ g variables or values, and round brackets indicate the choice of one of th\ e options)\r\ \n#\r\ \n# [:(local|global) \$anyVarMail \"address@domain.zone\";]\r\ \n# [:(local|global) \$anyVarSubj \"Any subject\";]\r\ \n# [:(local|global) \$anyVarMsg \"Any message\";]\r\ \n#\r\ \n# \$sendEvent [mode=(sms|mail|safe)] [to=(address@domain.zone|\$anyVarMa\ il)] [subj=(\"any subj\"|\$anyVarSubj)] msg=(\"any msg\"|\$anyVarMsg);\r\ \n\r\ \n#\r\ \n# Communication check function (example below)\r\ \n#\r\ \n\r\ \n:global pingSession do={\r\ \n\r\ \n :global pingTo1;\r\ \n :global pingTo2;\r\ \n :global pingCount;\r\ \n\r\ \n :local localCount;\r\ \n :local localPingStatus;\r\ \n\r\ \n :if ( [ :typeof \$myPingCount ] = \"nothing\" ) do={ :set localCount \ \$pingCount; } else={ :set localCount \$myPingCount; }\r\ \n\r\ \n :do {\r\ \n :set localPingStatus \\\r\ \n ( [/ping \$pingTo1 interface=\$pingFrom count=\$localCount] + \\\r\ \n [/ping \$pingTo2 interface=\$pingFrom count=\$localCount] );\r\ \n } on-error={}\r\ \n\r\ \n:return \$localPingStatus;\r\ \n}\r\ \n\r\ \n# Example\r\ \n#\r\ \n# :local \$intName \"Any-Interface-Name\";\r\ \n# :local pingStatus;\r\ \n#\r\ \n# :set pingStatus [ \$pingSession pingFrom=\$intName; ];\r\ \n# or\r\ \n# :set pingStatus [ \$pingSession pingFrom=\$intName myPingCount=8; ];\r\ \n\r\ \n#\r\ \n# Function of logging the results of checking channels\r\ \n# Requires ftp policy to work!\r\ \n#\r\ \n\r\ \n:global ispLogging do={\r\ \n\r\ \n :global stableConnectFrom;\r\ \n :global runLogCount;\r\ \n :global logFileNum;\r\ \n \r\ \n :local contentsFile;\r\ \n :local fileName;\r\ \n :local monthToNum;\r\ \n :local dateToPick;\r\ \n :local dateToLog;\r\ \n :local timeToLog;\r\ \n :local warnLevel;\r\ \n \r\ \n :if ( [ :typeof \$outInt ] = \"nil\" || [ :typeof \$outInt ] = \"nothi\ ng\" ) do={\r\ \n :local noInt \"The variable \\\"outInt\\\" is missing, the function \ ends.\";\r\ \n :log error (\"\$noInt\");\r\ \n :error \"\$noInt\"; }\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 :if ( [ :typeof \$logFileNum ] = \"nothing\" ) do={ :set logFileNum [ \ :toarray \"\" ]; }\r\ \n\r\ \n /file {\r\ \n :if ( [ :typeof ( \$logFileNum -> \"\$outInt\" ) ] = \"nothing\" ) d\ o={\r\ \n :do { :set ( \$logFileNum -> \"\$outInt\" ) [ get \"isp-stat/count\ ers/\$outInt.txt\" contents ];\r\ \n } on-error={\r\ \n /system routerboard print file=\"isp-stat/counters/\$outInt\";\r\ \n :delay 2s;\r\ \n set \"isp-stat/counters/\$outInt.txt\" contents=\"0\";\r\ \n :set ( \$logFileNum -> \"\$outInt\" ) [ get \"isp-stat/counters/\ \$outInt.txt\" contents ];\r\ \n }\r\ \n }\r\ \n\r\ \n :if ( [ :typeof \$runLogCount ] = \"nothing\" ) do={ :set runLogCoun\ t [ :toarray \"\" ]; }\r\ \n\r\ \n :if ( ( \$runLogCount -> \"\$outInt\" ) = \"66\" || [ :typeof ( \$ru\ nLogCount -> \"\$outInt\" ) ] = \"nothing\" ) do={\r\ \n :set ( \$runLogCount -> \"\$outInt\" ) 0;\r\ \n :set ( \$logFileNum -> \"\$outInt\" ) ( ( \$logFileNum -> \"\$outI\ nt\" ) + 1 );\r\ \n :do { set \"isp-stat/counters/\$outInt.txt\" contents=( \$logFileN\ um -> \"\$outInt\" );\r\ \n } on-error={\r\ \n /system routerboard print file=\"isp-stat/counters/\$outInt\";\r\ \n :delay 2s;\r\ \n set \"isp-stat/counters/\$outInt.txt\" contents=( \$logFileNum -\ > \"\$outInt\" );\r\ \n }\r\ \n } else={\r\ \n :set ( \$runLogCount -> \"\$outInt\" ) (( \$runLogCount -> \"\$o\ utInt\" ) + 1 );\r\ \n }\r\ \n }\r\ \n\r\ \n :if ( \$newFileAt = \"month\" ) do={\r\ \n :set fileName ( \$outInt . \"-\" . [:pick \$dateToPick 7 11] . \".\"\ \_. \\\r\ \n ( \$monthToNum -> [:pick \$dateToPick 0 3] ) . \"-\" . ( \$logFileNu\ m -> \"\$outInt\" ) );\r\ \n } else={\r\ \n :if ( \$newFileAt = \"day\" ) do={\r\ \n :set fileName ( \$outInt . \"-\" . [:pick \$dateToPick 7 11] . \ \".\" . \\\r\ \n ( \$monthToNum -> [:pick \$dateToPick 0 3] ) . \".\" . [:pick \$\ dateToPick 4 6] . \"-\" . \\\r\ \n ( \$logFileNum -> \"\$outInt\" ) );\r\ \n } else={\r\ \n :local noFile \"The variable \\\"newFileAt\\\" is missing, the\ \_function ends.\";\r\ \n :log error (\"\$noFile\");\r\ \n :error \"\$noFile\"; }\r\ \n }\r\ \n\r\ \n :if ( \$receivedPing < \$stableConnectFrom ) do={ :set warnLevel \"!\"\ ; }\r\ \n\r\ \n /file {\r\ \n :do { :set contentsFile [ get \"isp-stat/\$fileName.txt\" contents ]\ ; } on-error={\r\ \n /system routerboard print file=\"isp-stat/\$fileName\";\r\ \n :delay 2s;\r\ \n set \"isp-stat/\$fileName.txt\" contents=\"Interface;Warning;Date;\ Time;Received;Total;Level;Mode\"; \r\ \n :set contentsFile [ get \"isp-stat/\$fileName.txt\" contents ]; \r\ \n}\r\ \n set \"isp-stat/\$fileName.txt\" \\\r\ \n contents=\"\$contentsFile\\r\\n\$outInt;\$warnLevel;\$dateToLog;\$ti\ meToLog;\$receivedPing;\$totalPing;\$stableConnectFrom;\$startMode\";\r\ \n }\r\ \n}\r\ \n\r\ \n# Example\r\ \n#\r\ \n# \$ ispLogging outInt=(\"InterfaceName|\$ether1) [receivedPing=(\$ping|\ integer)] [totalPing=(\$ping|integer)] [startMode=(script|sms|manual|\"any\ -text\")] newFileAt=(day|month);\r\ \n\r\ \n#\r\ \n# Initialization of SMS reception and test sending\r\ \n#\r\ \n\r\ \n:if ( \$varOnly = \"yes\" ) do={\r\ \n :local varOnlySubj \"SMS reception is off!\";\r\ \n :local varOnlyMsg \"Initialization script has been executed, but the S\ MS reception enable section is off!\";\r\ \n\r\ \n \$sendEvent mode=mail subj=\$varOnlySubj msg=\$varOnlyMsg;\r\ \n :log warning (\"\$varOnlyMsg\");\r\ \n } else={\r\ \n /tool sms set receive-enabled=yes;\r\ \n :delay 10s;\r\ \n\r\ \n :local smsOn \"MikroTik rebooted! (send \\\":cmd 31337 script help\\\ \" for help)\";\r\ \n :local smsOnLog \"SMS reception enabled!\";\r\ \n :local smsErrSubj \"SMS transmission failed!\";\r\ \n :local smsErr \"The device is rebooted, but the SMS notification cou\ ld not be sent.\";\r\ \n :local smsErrLog \"Failed to enable SMS reception after reboot!\";\r\ \n\r\ \n :do { /tool sms send \$modemPort channel=\$smsChannel \"\$smsNumber\ \" message=\$smsOn;\r\ \n :log info (\"\$smsOnLog\");\r\ \n } on-error={\r\ \n /tool e-mail send to=\$localTo subject=\$smsErrSubj body=\$smsEr\ r;\r\ \n :log warning (\"\$smsErrLog\"); }\r\ \n\r\ \n :execute \"startup-music\";\r\ \n}\r\ \n\r\ \n# With love from Vladivostok."
Скрипт должен выполняться при запуске устройства и при внесении в него изменений. Параметры запуска смотрите в соответствующем разделе.
Это минимально необходимый набор для работы скрипта.
Обсуждение