MikroTik. Основы написания скриптов

Это основы написания скриптов для роутеров MikroTik. Функционал их достаточно велик, но его можно расширить с помощью написания скриптов.















Документация и примеры




Описание синтаксиса и примеров вы можете смотреть на следующих страницах:







Хранилище скриптов




В RouterOS есть специальное хранилище для скриптов — /system/script.




RouterOS - /system/script
RouterOS — /system/script




Хоть и возможно писать скрипты в окошке «Source«, но это совсем не удобно. А удобно для редактирования скриптов использовать терминал.




Для создания скрипта используется вот такая команда:




/system script add name=<имя скрипта>




А для его редактирования нужно использовать следующую команду:




/system script edit <имя скрипта> source




После выполнения этой команды в терминале откроется текстовый редактор, где вы сможете написать свой скрипт. Например:




RouterOS - пример скрипта




Чтобы сохранить скрипт и закрыть редактор используйте комбинацию клавиш Ctrl+O, а чтобы закрыть редактор без сохранения Ctrl+C.




Недостатком такого метода является то, что при написании скрипта не подсвечивается синтаксис. Он начинает подсвечиваться только после сохранения скрипта (Ctrl+O) и последующего его открытия (/system/script/ edit <имя скрипта> source). При этом новые строки остаются не подсвечиваемыми до нового сохранения скрипта. Это означает что после каждой правки вам придется сохранять и пере-открывать скрипт, чтобы убедиться что нет синтаксических ошибок.




Например предыдущий скрипт после сохранения и последующего открытия выглядит таким образом:




RouterOS - пример скрипта




А чтобы запустить наш скрипт нужно использовать следующую команду:




/system script run <имя скрипта> 




Например:




RouterOS - запуск скрипта




Автоматическое выполнение скриптов




На практике часто требуется выполнять скрипты автоматически в зависимости от каких-либо событий.




Часто скрипты выполняются планировщиком заданий — /system/scheduler.




RouterOS — /System/scheduler




В поле «Interval» вы должны ввести интервал повторений, в моём случает интервал равен 30 секундам. А в поле «On Event» пишется скрипт, или можно вызывать скрипт из хранилища, как сделано у меня.




Скрипты могут срабатывать не только по определённому интервалу. Ещё они могут выполняться при наступлении определённых событиях:




  • /tool/trafic/monitor — при превышении трафика, или наоборот при слишком низком трафике на каком-либо интерфейсе;



  • /tool/netwatch — при доступности или недоступности узла сети;



  • /ppp/profile — при подключении или отключении vpn-клиентов;



  • /ip/hotspot/user/profile — при подключении или отключении hotspot клиента;



  • /system/reset-configuration/run-after-reset — выполнить скрипт после сброса роутера.




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




Синтаксис




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




Написание команд




Команды в RouterOS строятся из следующих элементов:




  1. Путь к объекту;



  2. Команда;



  3. Параметры команды без значений;



  4. Параметры команды со значениями.




Вначале мы указываем путь к объекту, например ip адреса у нас находятся в /ip/address/.




RouterOS - /ip/addresses
RouterOS — /ip/addresses




Путь до объектов в нашем случае будет таким: /ip addresses. Вначале ставим слеш «/«, а затем между узлами пути ставятся пробелы.




Затем пишем команду, вот примеры возможных команд:




  • print — выведет нам список уже созданных объектов (например ip адресов);



  • add — позволяет сделать новый объект (например добавить ip адрес);



  • remove — используется для удаления объекта;



  • disable — используется для выключения объекта;



  • get — получить свойства объекта;



  • есть и другие команды, которые мы разберём позже.




После команды можем написать её параметры, причем вначале нужно использовать параметры без значений, а потом параметры со значениями. Например при добавлении IP-адреса в качестве параметров можно использовать адрес и интерфейс.




Вот некоторые примеры:




/ip address print
Flags: X - disabled, I - invalid, D - dynamic 
 #   ADDRESS            NETWORK         INTERFACE                                                                 
 0   192.168.10.1/24    192.168.10.0    bridge-lan                                                                
 1 D 172.24.101.252/32  5.187.73.6      justlan                                                                   
 2 D 10.10.0.2/32       10.10.0.1       sstp-out-k

/ip address print where address="192.168.10.1/24"
Flags: X - disabled, I - invalid, D - dynamic 
 #   ADDRESS            NETWORK         INTERFACE                                                                 
 0   192.168.10.1/24    192.168.10.0    bridge-lan

/ip address add address=192.168.5.1/24 interface=bridge-lan 
/ip address print                                          
Flags: X - disabled, I - invalid, D - dynamic 
 #   ADDRESS            NETWORK         INTERFACE                                                                 
 0   192.168.10.1/24    192.168.10.0    bridge-lan                                                                
 1 D 172.24.101.252/32  5.187.73.6      justlan                                                                   
 2 D 10.10.0.2/32       10.10.0.1       sstp-out-k                                                                
 3   192.168.5.1/24     192.168.5.0     bridge-lan

/ip address remove numbers=3
/ip address print
Flags: X - disabled, I - invalid, D - dynamic 
 #   ADDRESS            NETWORK         INTERFACE                                                                 
 0   192.168.10.1/24    192.168.10.0    bridge-lan                                                                
 1 D 172.24.101.252/32  5.187.73.6      justlan                                                                   
 2 D 10.10.0.2/32       10.10.0.1       sstp-out-k




Некоторые команды можно использовать без пути, такие как:




  • :local — создание локальной переменной;



  • :global — создание глобальной переменной;



  • :set — присвоить значение переменной;



  • :put — вывод в консоль;



  • :log — запись в журнал;



  • :delay — задержка.




Все они, как вы могли заметить, начинаются на двоеточие. Эти команды на примерах рассмотрим ниже!




Кстати, одна команда от другой разделяются либо знаком окончания строки, либо точной с запятой «;«. Я вам рекомендую всегда использовать точку с запятой, чтобы избежать путаницы.




Переменные




Можно использовать локальные и глобальные переменные. Локальные видны в пределах скрипта, а глобальные можно использовать разными скриптами. При объявлении глобальной переменной, она сохраняется в память роутера до перезагрузки.




Локальную или глобальную переменную можно создать таким образом:




:local myVar;
:global myVar;




Для того чтобы назначить переменной значение используется команда :set:




:set myVar "Hello World!";




А чтобы вывести значение переменной на терминал нужно использовать :put и название переменной. Но перед названием переменной нужно поставить знак «$»:




:put $myVar;




Вот пример однострочного скрипта:




:local myVar; :set myVar "Hello World!"; :put $myVar;
Hello World!




А ещё переменным можно присваивать значения сразу при объявлении.




:local myIP 192.168.1.1;




Массивы




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




С помощью команды :len можно узнать размер массива, а с помощью :pick вывести определённый элемент массива.




:local m (192.168.5.10, 192.168.5.15, 192.168.5.25);
:put [:len $m];
:put [:pick $m 0];




Кстати в этих примерах используется ещё один приём. Когда мы хотим внутри одной команды выполнить другую, то мы используем квадратные скобки. Так в нашем примере, результат одной команды «:len $m» будет выведен в терминал с помощью команды «:put«.




Задержка




Иногда после выполнения команды нужно подождать несколько секунд, а затем продолжить выполнять следующие команды. В этом случае применяется команда :delay <количество секунд>, например:




:local myVar; :set myVar "Hello World!"; :delay 10; :put $myVar;
Hello World!




При выполнении этого скрипта терминал подождет 10 секунд, а затем на нём появится строка «Hello World!».




Запись в журнал




Команда «:log» позволяет вам сохранить какую-нибудь запись в журнал (Log). Она используется таким образом — :log <тема> <сообщение>. Например так:




:log info "Hello!"




В логах, после выполнения этой команды, появится запись «Hello!» в теме «script, info«.




Результат выполнения команды заносим в переменную




Мы уже встречались с приёмом, когда одну команду нужно выполнить внутри другой команды. А в этом примере я покажу как используя этот приём занести результат выполнения одной команды в переменную. Это делается следующим образом: :set $<переменная> «$[<команда>]». То-есть результат команды будет занесен в переменную. А вот пример такого скрипта:




:local myVar; :set $myVar "$[/system identity get name]"; :put $myVar;
MikroTik




В примере выше результат выполнения команды «/system identity get name» будет помещён в переменную «myVar«. А после чего, с помощью команды :put, я вывожу значение переменной в терминал.




Получение свойств объекта




В предыдущем примере используется команда get. Она необходима, чтобы получить свойства объекта.




/system identity get name




По пути /system/identity можно указать имя вашего роутера. А с помощью команды «get» мы это имя получаем. То-есть с помощью пути /system identity мы перешли к объекту в котором хранится имя роутера, затем с помощью get мы получаем свойства этого объекта. Но все свойства нам не нужны, поэтому мы используем параметр name, чтобы получить именно имя роутера.




Циклы, блоки команд и условный оператор if




Можно использовать следующие циклы и условные операторы в RouterOS:




  • :while (<условие>) do={<команды>}



  • :do {<команды>} :while=(<условие>)



  • :for <var> from=<int> to=<int> step=<int> do={<команды>}



  • :foreach <var> in=<array> do={<commands>}



  • :if(<условие>) do={<команды>} else={<команды>}




Вот пример работы условного оператора :if:




{
   :local myBool true;
   :if ($myBool = false) do={ :put "value is false" } else={ :put "value is true" }
}




Кстати, блок команд можно брать в фигурные скобки, как показано выше. Это можно применять прям в терминале для составления одной команды (не скрипта). То есть Вы открываете скобку и начинаете записывать ваш скрипт, после чего вы закрываете скобку, нажимаете Enter и скрипт выполняется.







Обработка ошибок




Если какая-то команда может завершиться с ошибкой и это не должно привести к прекращению работы скрипта. Тогда нужно ошибки обрабатывать. Делается это с помощью do {<блок команд>} on-error={<другой блок команд>}. Например так:




do {:put [:resolve test.ru]} on-error={:put "resolver failed"};
resolver failed




Здесь же продемонстрирован и пример одной команды внутри другой с помощью квадратных скобок. То есть выполняется команда :resolve test.ru, а её результат выводится в терминал с помощью :put. Но если :resolve test.ru завершиться ошибкой, то выполнится блок команд после on-error. И так как test.ru у меня не резолвится, то выполнилась команда :put «resolver failed».








Обратная связь




Я совсем немного пишу скрипты для роутеров MikroTik, и редко использую терминал, предпочитая ему WinBox. Поэтому если Вы в статье найдёте ошибки или неточности, то напишите в комментариях. И я поправлю или дополню эту статью.




Другие статьи посвященные MikroTik доступны здесь.



2021-11-22T10:53:52
MikroTik