Это основы написания скриптов для роутеров MikroTik. Функционал их достаточно велик, но его можно расширить с помощью написания скриптов.
Документация и примеры
Описание синтаксиса и примеров вы можете смотреть на следующих страницах:
- Описание синтаксиса и небольшие примеры;
- Различные примеры скриптов;
- Советы и приемы создания скриптов.
Хранилище скриптов
В RouterOS есть специальное хранилище для скриптов — /system/script.
Хоть и возможно писать скрипты в окошке «Source«, но это совсем не удобно. А удобно для редактирования скриптов использовать терминал.
Для создания скрипта используется вот такая команда:
/system script add name=<имя скрипта>
А для его редактирования нужно использовать следующую команду:
/system script edit <имя скрипта> source
После выполнения этой команды в терминале откроется текстовый редактор, где вы сможете написать свой скрипт. Например:
Чтобы сохранить скрипт и закрыть редактор используйте комбинацию клавиш Ctrl+O, а чтобы закрыть редактор без сохранения Ctrl+C.
Недостатком такого метода является то, что при написании скрипта не подсвечивается синтаксис. Он начинает подсвечиваться только после сохранения скрипта (Ctrl+O) и последующего его открытия (/system/script/ edit <имя скрипта> source). При этом новые строки остаются не подсвечиваемыми до нового сохранения скрипта. Это означает что после каждой правки вам придется сохранять и пере-открывать скрипт, чтобы убедиться что нет синтаксических ошибок.
Например предыдущий скрипт после сохранения и последующего открытия выглядит таким образом:
А чтобы запустить наш скрипт нужно использовать следующую команду:
/system script run <имя скрипта>
Например:
Автоматическое выполнение скриптов
На практике часто требуется выполнять скрипты автоматически в зависимости от каких-либо событий.
Часто скрипты выполняются планировщиком заданий — /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 строятся из следующих элементов:
- Путь к объекту;
- Команда;
- Параметры команды без значений;
- Параметры команды со значениями.
Вначале мы указываем путь к объекту, например ip адреса у нас находятся в /ip/address/.
Путь до объектов в нашем случае будет таким: /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 доступны здесь.