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

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


mikrotik:rb3011uias:routeros:system:scripts:variables_initialization

Инициализация глобальных переменных и SMS

Самый важный, я бы даже сказал, что основополагающий скрипт, т.к. без его загрузки при запуске устройства, другие скрипты не будут работать.

Им инициализируются:

  1. глобальные переменные;
  2. глобальные функции;
  3. прием и отправка SMS;
  4. воспроизведение музыки! :-D

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

Используется для тестирования. Если его раскомментировать, скрипт отработает на 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;

Функция отправки СМС и (или) Email из скриптов

: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

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

  :if ( $mode = "sms" ) do={
    :do { /tool sms send $modemPort channel=$smsChannel "$smsNumber" message=$msg; } on-error={ :log error ("$errorTxt"); }
    }
Режим Email

Отправляем только 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 так же может быть передано другой переменной или быть указано простым текстом в кавычках.

Важно!

  • SMS не поддерживает кириллицу.
  • Для передачи кириллицы в Email текст нужно или импортировать с текстом скрипта или набирать непосредственно из редактора кода RouterOS (подробнее в статье о фэйловере).

Функция проверки состояния каналов

: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

Инициализация приема SMS и тестовая отправка

Если переменная в начале скрипта раскомментирована, просто пишем в лог об этом и отправляем 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";
}

Последней строчкой включаем победную музыку, оповещающую серверную об удачном старте. 8-)

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

variables-initialization.rsc
/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."

Запуск скрипта

Скрипт должен выполняться при запуске устройства и при внесении в него изменений. Параметры запуска смотрите в соответствующем разделе.

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

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

  • read,
  • write,
  • policy,
  • test,
  • sensitive.

Дисклеймер

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

Обсуждение

Ваш комментарий:
X T C​ J J W J F C T G X D W C᠎ O
 
Последнее изменение: 2022/02/12 11:40 (внешнее изменение)