-
alexanderx10
- Сообщения: 52
- Зарегистрирован: 23 дек 2013, 14:06
Коллеги кто нибудь знает инструмент для поиска ошибок в скрипах для Router OS ?? Скрипты раньше не писал, вот пришлось начинать.
А писать методом научного тыка как то не хочеться. Тем более в самом начале.
-
vqd
- Модератор
- Сообщения: 3605
- Зарегистрирован: 26 сен 2013, 14:20
- Откуда: НСК
- Контактная информация:
28 авг 2014, 20:08
copy/paste в консоль
-
-user-
- Сообщения: 30
- Зарегистрирован: 21 мар 2013, 10:05
29 авг 2014, 12:00
alexanderx10 писал(а):Коллеги кто нибудь знает инструмент для поиска ошибок в скрипах для Router OS ?? Скрипты раньше не писал, вот пришлось начинать.
А писать методом научного тыка как то не хочеться. Тем более в самом начале.
сори что влезаю с нубскими советами…, но мне кажеться я бы начал копать с:
Starting from v6.2 scripting has ability to catch run-time errors.
For example, :reslove command if failed will throw an error and break the script.
Код: Выделить всё
:do {
:put [:resolve www.example.com];
} on-error={ :put "resolver failed"};
:put "lala" output:
resolver failed
lala
а по хотелке: вместо put наверное log использовать (если напрягает в терминале забивать)
не, не угадал?

или нужны именно проверки на правильность самого написания команд? ))) типо подсветка синтаксиса и прочее?
-
alexanderx10
- Сообщения: 52
- Зарегистрирован: 23 дек 2013, 14:06
29 авг 2014, 14:26
-user- писал(а):
alexanderx10 писал(а):Коллеги кто нибудь знает инструмент для поиска ошибок в скрипах для Router OS ?? Скрипты раньше не писал, вот пришлось начинать.
А писать методом научного тыка как то не хочеться. Тем более в самом начале.сори что влезаю с нубскими советами…, но мне кажеться я бы начал копать с:
Starting from v6.2 scripting has ability to catch run-time errors.
For example, :reslove command if failed will throw an error and break the script.Код: Выделить всё
:do {
:put [:resolve www.example.com];
} on-error={ :put "resolver failed"};
:put "lala"output:
resolver failed
lalaа по хотелке: вместо put наверное log использовать (если напрягает в терминале забивать)
не, не угадал?
![]()
или нужны именно проверки на правильность самого написания команд? ))) типо подсветка синтаксиса и прочее?
ДА. Прямо в цель!!
По порядку copy / paste знаю такюй фунцию )) уже хорошо.
Да типо подстветки синтаксиса и прочее. Что имеется ввиду под прочее.. Допусти если писать что на php есть программа phpstorm которая не только подсвечивает синтаксис но и указавает на ошибки, у казывать на ошибки может и сам php если включить такую опцию. Незряли все проф. инструменты написания кода содержит дебагер. Не просто же его туда впихивают. Мне предстоит написать ближаещее время десяток больших скриптов, и так как я с этим раньше не сталкивался, мне будет трудновато понять где я забыл поставит скобку или запятую после echo, if , else и так далее.
-
-user-
- Сообщения: 30
- Зарегистрирован: 21 мар 2013, 10:05
29 авг 2014, 15:23
alexanderx10 писал(а):Да типо подстветки синтаксиса и прочее
Ну это только, как Вам ответили выше )) копипастингом в терминал…. о других способах не видел информации, да и зачем что-то другое нужно, если оно уже полнофункциональное есть….
Я сам пока делал все в NOTEPAD++ он проблемы со скобками хорошо показывает…. а потом копипаст в терминал… и там уже и место ошибки покажет.
wolf_ktl писал(а):А я делаю вывод логов с нужными переменными )))
я думаю, так же буду поступать в дальнейшем… пока put хватало (но я еще с МТ — без году неделя
)
Debug mikrotik script
В mikrotik нет встроенной подсветки синтаксиса в System — scripts. Зато подсветка есть в терминале. Если нужно быстро найти ошибку сохраняем наш скрипт, в терминале пишем
- /system script print from=script name
где script name — имя нашего скрипта.

Популярные сообщения из этого блога
Zabbix agent установка и настройка

Zabbix agent — основная информация Важное преимущество — разработан командой Zabbix именно под свой Zabbix server. — разработан на языке C — может собирать данные с процессора, памяти, диска и сетевого интерфейса — малый размер и низкий ресурс — благодаря малой занимаемой площади и широкой настройкой агент может работать на устройствах с ограниченными ресурсами — конфигурации мониторинга централизованы на сервере Zabbix, что упрощает управление агентом Zabbix — может использовать один файл конфигурации на всех серверах. — может работать на различных поддерживаемых платформах, включая Linux, UNIX и Windows Linux IBM AIX FreeBSD NetBSD OpenBSD HP-UX Mac OS X SolarisWindows: все версии для рабочих станций и серверов начиная с 2000 Функции агента Ниже приведен список проверок Zabbix агента из коробки. Следует отметить, однако, что встроенные функции агента могут быть расширены с помощью следующих методов: загружаемые модулей , пользовательских п
Webdav точки монтирования
https://storagemadeeasy.com/CloudDav/ через эту шнягу можно по WebDav подключать облака, которые даже не поддерживают webdav. До 3 штук сразу. Я через нее подключил dropbox и google drive точка монтирования https://webdaveu.storagemadeeasy.com LOGIN PASSWORD https://webdav.storagemadeeasy.com (for US Server) https://webdaveu.storagemadeeasy.com (for EU Server) « Яндекс Диск » (см. Работа через WebDAV ). Строка в «/etc/fstab» может иметь вид https: // webdav.yandex.ru: 443 / media / Yandex davfs user,rw,noauto 0 0 В этом примере явно указан порт для подключения. Это не обязательно, если поставщик облачного диска использует стандартные порты: 80 для HTTP и 443 для HTTPS. « 4shared » (см. What is WebDav and how to use it ). Строка в «/etc/fstab» может иметь вид https: // webdav.4shared.com / / media / 4shared davfs user,rw,noauto 0 0 « IDriveSync » (см. IDriveSync join hands with WebDAV ). Строка в «/etc/fstab» может иметь вид https: // d
mikbill расшифровка завершений сессий
Сессии Lost-Сarrier Потеря несущей, чаще всего у абонента потери в? локалке? и нужно проверять?физику линии. Так же может быть вызвано отключением? подключения по локальной сети? у абонента вместо отключения ?интернет соединения? Для Wi-Fi и других роутеров означает что выключили питание на этом устройстве. User-Request Нормальное завершение Сессии. Пользователь закрыл соединение. Online Пользователь находится в интернете. Admin-Reboot Перезагрузка сервера доступа(NAS). Сервер корректно завершил соединение. BILL-Request Выброшен из интернета из админки биллинга. NAS-Request Сервер доступа по запросу завершил сессию ( те кто-то его выкинул ). NAS-Error Вызвана неправильными параметрами сессии, устранять администратору. Port-Error Вызвана неправильными параметрами сессии, устранять администратору. Admin Reset Сессия или порт сброшены администратором. User Error Ошибка в полученных от пользователя данных, вызвавшая прекращение сеанса
Это основы написания скриптов для роутеров 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 доступны здесь.
Сводка

Имя статьи
MikroTik. Основы написания скриптов
Описание
Это основы написания скриптов для роутеров MikroTik. Функционал их достаточно велик, но его можно расширить с помощью написания скриптов
Предисловие. Это можно не читать ))
Есть много хороших и не очень руководств по языку скриптов Mikrotik, но подробного описания как работать с функционалом(объектами) я не нашел. Пришлось собирать информацию по крупицам, разбираться по примерам. Как известно, что бы закрепить и систематизировать полученные знания, полезно их рассказать другим. Поэтому, рискну изложить то, что понял сам из разрозненных источников.
На первый взгляд может показаться, что очень много написанного не имеет отношения к написанию скриптов. Но это только на первый взгляд 😉
Подготовка
Хоть я и старался максимально подробно изложить материал, но перед началом работы имеет смысл ознакомиться с основами работы в терминале Mikrotik. Это и будут первые шаги. Вот достойный материал на эту тему: http://mikrotik.vetriks.ru/wiki/%D0%94%D0%BB%D1%8F_%D0%BD%D0%B0%D1%87%D…
Поехали
Для примера будем работать с DHCP сервером.

Открываем терминал, пункт меню «New Terminal» и вводим команду: /ip dhcp-server и жмем кнопку табуляции(далее <TAB>). Получим такой вывод:

Здесь мы видим доступные для продолжения ввода команды значения. То что подсвечено «синим» цветом, это подразделы. В WinBox их можно увидеть в виде вкладок. Нас же, более всего интересуют «фиолетовые» команды. Пробуем набирать print и <ENTER>. На выводе получим список всех(в примере один) настроенных DHCP серверов:

Кстати, после print то же можно нажать <TAB>. Поиграйтесь с разными параметрами.
Усложняем задачу. Идем на вкладку Leases. В этом примере она выглядит так:

Отключим(не удалим(remove), а именно отключим(disable)) резервирование IP адреса для хоста, у которого текущий адрес 192.168.254.21. На скриншоте мы видим результат — команды, их вывод и отключенная запись резервирования. Разберем подробно.

Вводим: /ip dhcp-server lease <TAB> и наблюдаем список команд. По смыслу понимаем что нам подходит команда disable, но мы сделаем вид что ее нет, и в академических целях пойдем более сложным путем. Так же видна некая команда set, вероятно она устанавливает какие-то параметры. Посмотрим что она может.
Продолжаем вводить: set <TAB>. Теперь мы видим список «зеленых» параметров, которые мы можем использовать в команде set. Обратите внимание, что параметр numbers выделен жирным цветом — он обязательный. Следуя логике можно предположить, что это некий идентификатор(номер), однозначно указывающий на изменяемый командой set объект.
Так где же нам узнать этот номер? Например через команду print, вводим:
/ip dhcp-server lease print
Следует отметить, что номера выводимые командой print не постоянны, и могут измениться при следующей команде print.
Пробуем ввести: /ip dhcp-server lease set disabled=<TAB> и видим какие значения может принимать параметр, дописываем yes и <ENTER>. Упс, что за вопрос numbers? Да-да, тот самый номер, из первой колонки таблицы, команды print. В нашем случае вводим: 7<ENTER>.
Но все это можно сделать одной командой:
/ip dhcp-server lease set 7 disabled=yes
Забегая вперед, замечу, что при попытке получить значение disabled, командой:
:put [/ip dhcp-server lease get 7 disabled]
вы получите булево значение true или false. Это важно при использовании в скриптах, такая особенность вас может поджидать в самом неожиданном месте. О_о, а откуда взялся get, его ведь не было в списке доступных команд? Об этом то-же позже…
Чет какая-то фигня заметит пытливый читатель )) Верно, фигня. Теперь выполним задачу одной командой. Если помните, среди доступных команд есть find ее-то мы и будем использовать.
Обратите внимание на эти команды:

В первой строке: От корня иерархии объектов микротика мы двигаемся в раздел lease DHCP-сервера, где командой set изменяем значение параметра disabled у 7-го объекта.
Во второй и третьей строке проделывается то-же самое, только немного иначе. Сначала мы переходим в контекст — /ip dhcp-server lease, а затем в этом контексте выполняем команду с параметрами: set 7 disabled=yes
Теперь в нашей команде /ip dhcp-server lease set 7 disabled=yes сотрем цифру 7 и напишем [ find ]. После слова find нажмем <TAB> и увидим список параметров по которым мы можем выполнить поиск в списке объектов выделенных адресов.
Дописываем наш find, должно получиться так:
/ip dhcp-server lease set [find address=192.168.254.21] disabled=yes

Если кто заметил, в тексте IP-адрес экранирован кавычками, а на скриншоте нет. Можно использовать кавычки, можно не использовать — работает всяко.
Что такое find и как оно так произошло?
Команду find следует разобрать отдельно. Это одна из самых часто используемых команд в скриптах RouterOS. Она возвращает внутренний(это не тот номер, что возвращает print, но указывает на тот же объект) номер/номера объектов удовлетворяющих условию.

Если ввести команду(как в первой строке):
/ip dhcp-server lease find address=192.168.254.21
в надежде увидеть номер, то ничего не произойдет. Это как вызвать функцию, а возвращаемый ей результат не обработать.
Поэтому, используем :put для вывода возвращаемого значения(вторая строка). На выходе получаем шестнадцатеричное число DBB. Его можно использовать в качестве значения numbers(раньше мы брали номер из команды print).
Если вы внимательно посмотрите, то заметите что во второй строке
:put [ip dhcp-server lease find address=192.168.254.21]перед ip нет символа /Эта команда выполнится, так как мы и так находимся в корне иерархии объектов. Но если нам перейти в другой контекст, то тут-же получим ошибку.
Не много отвлеклись, но вернемся к нашей команде
/ip dhcp-server lease set [find address=192.168.254.21] disabled=yes
Что здесь происходит:
-
Устанавливается контекст /ip dhcp-server lease
-
Внутри контекста(пункт 1) выполняется find address=192.168.254.21 и возвращается значение *dbb, как если бы выполнили команду
/ip dhcp-server lease find address=192.168.254.21 -
Внутри контекста(пункт 1) выполняется set(со значением numbers равным *dbb), который присваевает параметру disabled значение yes
В развернутом виде это аналогично:
/ip dhcp-server lease set [/ip dhcp-server lease find address=192.168.254.21] disabled=yes
Таким образом мы видим, что квадратные скобки позволяют выполнять команды во время выполнения других команд и передавать результат «на верх».
Скрипт
На основе вышесказанного напишем скрипт получающий IP адреса клиентов DHCP сервера, отвечающих следующим условиям:
-
Зарезервированы, т.е. IP-адрес закреплен за MAC
-
В настоящее время в сети и имеют активную аренду адреса.
Полученные адреса поместить в список доступа(aclGrantIPs). Если клиент отключился, то удалить его IP из этого списка.
Скопируем скрипт и вставим его в терминал:
/ip dhcp-server lease
:foreach i in=[find] do={
:local addrTMP [get $i address]
:if ([get $i status]="bound" && ![get $i dynamic]) do={
:do {/ip firewall address-list add address=$addrTMP list=aclGrantIPs} on-error={}
} else={
:do {/ip firewall address-list remove [find address=$addrTMP list=aclGrantIPs]} on-error={}
}
}

Разберем построчно, что здесь происходит.
Устанавливаем контекст /ip dhcp-server lease
В цикле перебираем все выделенные адреса.
Если в терминале выполнить :put [/ip dhcp-server lease find] то будет выведен массив внутренних идентификаторов объектов/записей аренды адресов.
![]()
Это и проделывается в строке
:foreach i in=[find] do={
что эквивалентно
:foreach i in=[/ip dhcp-server lease find] do={
или в рассматриваемом случае(со значениями)
:foreach i in=[*d;*26;*86;*141;*143;*1db;*1f3;*dbb;*dc1] do={
Создаем и инициализуем локальную переменную addrTMP значением содержащим IP адрес клиента. Обратите внимание, при создании переменной знак $ в начале не ставится, а при использовании ставится.
:local addrTMP [get $i address]
что эквивалентно
:local addrTMP [/ip dhcp-server lease get $i address]
где $i по порядку подставляется из массива [*d;*26;*86;*141;*143;*1db;*1f3;*dbb;*dc1] циклом :foreach
Аналогично предыдущему шагу, проверим значение параметров status и dynamic.
:if ([get $i status]="bound" && ![get $i dynamic]) do={
Наблюдая за поведением DHCP сервера, на вкладке Leases, можно предположить, что:
- параметр status со значением bound говорит нам о том, что клиент недавно запросил/подтвердил свой адрес.
- параметр dynamic определяет, что адрес динамический и возвращает булево значение true или false соответственно.
Если выполняются условия, что это DHCP клиент, со статической привязкой адресов и активен в настоящее время, то добавляем его в список доступа командой:
/ip firewall address-list add address=$addrTMP list=aclGrantIPs
Причем заметьте, что команда обернута в обработчик ошибок:
:do {} on-error={}
Это сделано, что-бы скрипт не останавливался «в тихую» с ошибкой, в случае если адрес уже есть в списке.
Если условие не выполняется, то удаляем запись с этим IP из списка. Например, наш клиент отключился, или у него администратор снял статическое резервирование адреса.
/ip firewall address-list remove [find address=$addrTMP list=aclGrantIPs]
Для удаления записи используется команда remove. Которая как get, set и еще некоторые другие команды, использует в качестве параметра numbers внутренний номер объекта. В этом случае, объект — это запись в IP — Firewall — Address List.
Команда find может искать по нескольким параметрам в одном запросе.
PS Теперь, когда многие вещи прояснились, можно ознакомиться с официальным описанием скриптового языка RouterOS или его переводом.
PSS Помнится я писал — «О_о, а откуда взялся get? Об этом позже…». Я сам не знаю почему так 🙂 Возможно когда-нибудь узнаю и здесь напишу.
