Скрипты в Mikrotik

В данной статье дано краткое объяснение по основным моментам написания скриптов для Mikrotik.

За подробной информацией обращайтесь к руководству: https://wiki.mikrotik.com/wiki/Manual:Scripting или тоже самое https://help.mikrotik.com/docs/

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

В RouterOS есть удобная командная строка (CLI). Попасть в нее можно подключившись к оборудованию Mikrotik по Winbox и открыв «New Terminal» или подключившись по SSH. Мы можем написать скрипт в любом текстовом редакторе, а затем скопировать и вставить его в командную строку Mikrotik. Скрипт выполнится.

Также мы можем сохранить написанный скрипт, для этого в Mikrotik есть меню System | Scripts куда можно добавить наш скрипт и вызывать его по расписанию или вручную.

Что мы можем написать в скрипте
  • Команды начинаются с символа «:», либо с символа «/», либо без начального символа
    Символ «:» — глобальная команда
    Символ «/» — начало пути к нужному меню
  • Далее может идти путь к нужному меню
  • Далее идет команда (глобальная или команда пункта меню)
  • Далее могут идти неименованные параметры
  • Далее могут идти именованные параметры вида param=value

[prefix] [path] command [uparam] [param=[value]] .. [param=[value]]

Команда завершается символом «;» либо переходом на новую строку. Команду можно взять в скобки (), [], {} в этом случае символ окончания не нужен

Глобальная команда put

:put <expression> — выводит выражение на консоль

:put»Hello!»;

Hello!

Команда меню print

print — выводит значения пунктов меню

Пример

/interface bridgeprint

Flags: X - disabled, R - running 
 0 R name="bridge1" mtu=auto actual-mtu=1500 l2mtu=1598 arp=enabled 
     arp-timeout=auto mac-address=08:55:31:3A:37:DC protocol-mode=rstp 
     fast-forward=yes igmp-snooping=no auto-mac=yes ageing-time=5m 
     priority=0x8000 max-message-age=20s forward-delay=15s transmit-hold-count=6 
     vlan-filtering=no dhcp-snooping=no 

 1 R name="bridge2" mtu=auto actual-mtu=1500 l2mtu=1598 arp=enabled 
     arp-timeout=auto mac-address=08:55:31:3A:37:DF protocol-mode=rstp 
     fast-forward=yes igmp-snooping=no auto-mac=yes ageing-time=5m 
     priority=0x8000 max-message-age=20s forward-delay=15s transmit-hold-count=6 
     vlan-filtering=no dhcp-snooping=nointer

Параметр «as-value» возвращает массив значений, чтобы вывести этот массив в консоль нужно использовать команду «put»

Пример

:put[/interface bridgeprint as-value]

Вывод получается неструктурированный в одну строку

.id=*7;actual-mtu=1500;ageing-time=00:05:00;arp=enabled;arp-timeout=auto;auto-mac=true;comm
ent=;dhcp-snooping=false;fast-forward=true;forward-delay=00:00:15;igmp-snooping=false;l2mtu
=1598;mac-address=08:55:31:3A:37:DC;max-message-age=00:00:20;mtu=0;name=bridge1;priority=32
768;protocol-mode=rstp;transmit-hold-count=6;vlan-filtering=false;.id=*8;actual-mtu=1500;ag
eing-time=00:05:00;arp=enabled;arp-timeout=auto;auto-mac=true;comment=;dhcp-snooping=false;
fast-forward=true;forward-delay=00:00:15;igmp-snooping=false;l2mtu=1598;mac-address=08:55:3
1:3A:37:DF;max-message-age=00:00:20;mtu=0;name=bridge2;priority=32768;protocol-mode=rstp;tr
ansmit-hold-count=6;vlan-filtering=false

На самом деле тут массив хэшей (хэш — это массив у которого вместо порядковых номеров идут имена). Условно такой массив хэшей можно представить так:

[
    {
        .id         => *7
        actual-mtu  => 1500
        arp         => enabled
        comment     => ""
        l2mtu       => 1598
        mac-address => 08:55:31:3A:37:DC
        name        => bridge1
    }

    {
        .id         => *8
        actual-mtu  => 1500
        arp         => enabled
        comment     => ""
        l2mtu       => 1598
        mac-address => 08:55:31:3A:37:DF
        name        => bridge2
    }
]

Можем например вывести в консоль первый элемент массива. Для этого используется символ «->» (и обязательно круглые скобки):

:put([/interface bridgeprint as-value]->0)

.id=*7;actual-mtu=1500;ageing-time=00:05:00;arp=enabled;arp-timeout=auto;auto-mac=true;comm
ent=;dhcp-snooping=false;fast-forward=true;forward-delay=00:00:15;igmp-snooping=false;l2mtu
=1598;mac-address=08:55:31:3A:37:DC;max-message-age=00:00:20;mtu=0;name=bridge1;priority=32
768;protocol-mode=rstp;transmit-hold-count=6;vlan-filtering=false

Или можем вывести элемент под именем «mac-address» первого элемента массива (обязательно кавычки):

:put([/interface bridgeprint as-value]->0->»mac-address»)

08:55:31:3A:37:DC

Переменные

Объявление переменных:

:global a;
:global b "value";
{
    :local c;
    :local d "value";
}

Назначение переменных:

:seta«value»;

Использование переменных:

:put$a;

Циклы

Есть три варианта циклов:

1) foreach

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

Пример

:foreach a in=[/interface print as-value where name~»ether»] do={:put ($a->»name»)};

ether1
ether2
ether3
ether4
2) for

:for <var> from=<int> to=<int> step=<int> do={ <commands> }

Пример

:for a from=1 to=4 do={:put «ether$a«};

ether1
ether2
ether3
ether4
3) do while, while do
:do { <commands> } while=( <conditions> );
:while ( <conditions> ) do={ <commands> };

Примеры

{
    :local a 0;
    :do {:set a ($a+1); :put "ether$a"} while=($a < 4)
}
{
    :local a 0;
    while ($a < 4) do={:set a ($a+1); :put "ether$a"}
}

Вывод одинаковый:

ether1
ether2
ether3
ether4
Условное выражение IF

:if (<condition>) do={<commands>} else={<commands>}

Пример

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

a is false

Операторы сравнения

<   >   =   <=   >=   !=

Логические операторы

!   && (and)   || (or)   in

Оператор in позволяет проверить попадает ли один диапазон ip-адресов в другой.

Оператор «~»

«~» — оператор сравнения с регулярным выражением (расширенное регулярное выражение POSIX)

Пример

ip route print where dst-address~"172\\."

«172\\.» — регулярное выражение, которое соответствует всем значениям где есть «172.»

Flags: X - disabled, A - active, D - dynamic, C - connect, S - static, r - rip, b - bgp, o - ospf, m - mme... 
 #      DST-ADDRESS        PREF-SRC        GATEWAY            DISTANCE
 0 ADC  172.16.1.2/32      172.16.1.1                0

 

Посмотреть тип элемента

Пример

{
    :put [:typeof a];
    :put [:typeof 10];
    :put [:typeof true];
    :put [:typeof (1,2,3,"value")];
    :put [:typeof [/interface print as-value] ];
    :put [:typeof 192.168.1.1]
    :put [:typeof 192.168.1.1/24]
}
str
num
bool
array
array
ip
ip-prefix