Библиотека функций для MikroTik RouterOS

А почему бы и нет?

Предистория

Вот совсем не давно посетила меня одна мысль, а почему бы мне не сделать что то на подобии Edelweiss только для MikroTik’а? Раз уж JS Edelweiss я не описываю #ибоЛень так как достаточно большая она и времени затянет много, а тут можно начать так сказать с чистого листа и постепенно всё описать… Собственно начинаем!

Суть задачи

В ряде скриптов у меня стали участвовать одни и те же функции, такие как работа со временем, озвучка действий и тд. Тут значит возникает идея, а почему бы не вынести их в :global? Помучившись пару часов на тему единого массива с функциями, я пришёл к неутешительному выводу, что RouterOS так не умеет и жить всем функциям отдельными переменными. Смирившись с сей траблой я поставил пару экспериментов и начал собирать скрипт. Эту статью я буду пополнять по мере создания функций и уровню их полезности на мой взгляд. В случае если у кого-то возникнут предложения или коррективы по данному вопросу, буду рад участию. Далее следует набор функций, в формате «как есть».

Edelweiss на GitHub
Edelweiss на GitHub

Для того чтобы воспользоваться функциями библиотеки не только из консоли но и в других скриптах, необходимо добавить в эти скрипты глобальные переменные библиотеки. Как только переменные добавлены, функции становятся доступными для скрипта локально.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# Добавляем в том случае, если библиотека не стартует вместе с системой.
/system script run "Edelweiss";
# Перечисляем нужные функции. Не стоит включать в каждый скрипт все функции сразу,
# добавляем только те, которые будут реально использоваться.
	:global mlFrm;
	:global syNme;
	:global cuDte;
	:global beMel;
	:global deArp;
	:global deCon;
	:global foDte;
	:global ifSta;
	:global ifDis;
	:global ifRun;
	:global flDel;
	:global mkDir;
	:global flCre;

Часто используемые переменные

1
2
3
4
5
6
7
8
# Версия и дата её выхода. 
:global Edelweiss "vX.XX XX.XX.XX";
# Поле "от кого" для E-mail. 
:global mlFrm [/tool e-mail get from];
# Имя системы. 
:global syNme [/system identity get name];
# Текущие дата и время. 
:global cuDte do={return ([/system clock get date]." ".[/system clock get time]);}

Звуковое оформление для скриптов

Функция отвечает за озвучку действий скриптов. На входе воспринимает три массива — частота звука (Frequency), длительность звука (Length) и длительность задержки между звуками (Delay). Данные указываются в герцах и миллисекундах.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# Применение:
# $beMel Frequency=({"1568.0"; "1318.5"; "1046.5"}) Length=({"100"}) Delay=({"100"})
# $beMel Frequency=({"1568.0"; "1318.5"; "1046.5"}) Length=({"100"; "200"; "300"}) Delay=({"100"; "200"; "300"})

:global beMel do={
	set $Nm [len $Frequency];
	do {
		if (([len $Length])>1) do={set $Ln [($Length->$Nm)];} else={set $Ln [($Length->0)];}
		if (([len $Delay])>1) do={set $Dn [($Delay->$Nm)];} else={set $Dn [($Delay->0)];}
		execute "beep frequency=$[($Frequency->$Nm)] length=$($Ln)ms ";
		delay "$($Dn+10) ms";
		set $Nm ($Nm-1);
		set $Ln ($Ln-1);
	} while ($Nm>-1);
	delay 500ms;
}

Удаляем все ARP записи

1
2
3
4
5
6
7
8
# Применение:
# $deArp

:global deArp do={
	[/ip arp print without-paging];
	set $Ia [/ip arp print count-only];
	for I from=0 to=($Ia-1) do={[/ip arp remove $I];}
}

Удаляем все соединения фаервола (аналогично предидущему)

1
2
3
4
5
6
7
8
# Применение:
# $deCon

:global deCon do={
	[/ip firewall connection print without-paging];
	set $Ia [/ip firewall connection print count-only];
	for I from=0 to=($Ia-1) do={[/ip firewall connection remove $I];}
}

Работа с датой и временем

Функция конвертирует дату и время формата Feb/25/2017 14:18:12 в два варианта, первый — это количество секунд со дня творения каледраля от рождества Христова и второй — вот такого вида 25-02-2017-18-43 для формирования удобоваримых имён файлов к примеру.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# Применение:
# ([$foDte Date=[$cuDte]]->0) - Возвращает секунды.
# ([$foDte Date=[$cuDte]]->1) - Возвращает форматированную дату и время.
# ([$foDte Date=[/file get number=НомерФайла value-name=creation-time]]->0) - дата создания файла в секундах.

:global foDte do={
	set $dfy 0;
	set $yar [pick $Date 7 11];
	set $mth [pick $Date 0 3];
	set $day [pick $Date 4 6];
	set $hur [pick $Date 12 14];
	set $min [pick $Date 15 17];
	set $sec [pick $Date 18 20];
	set $mts ("jan","feb","mar","apr","may","jun","jul","aug","sep","oct","nov","dec");
	set $mtd {0;31;28;31;30;31;30;31;31;30;31;30;31};
	set $mtn ([find $mts $mth -1]+1);
	set $yrd (($yar*365)+($yar / 4));
	set $cmd ($mtd->$mtn);
	set $conA $mtn;
 
	do {
		set $conA ($conA-1);
		set $dfy ($dfy+($mtd->$conA));
		if ($conA=0) do={set $dfy ($dfy+$day);}
	} while ($conA>0);
	if ($mtn<=9) do={set mtn ("0".$mtn);}
	return {((($yrd+$dfy)*86400)+($hur*3600)+($min*60)+$sec);($day."-".$mtn."-".$yar."-".$hur."-".$min)};
}

Состояние интерфейсов

Функция возвращает состояние активности интерфесов (running) заданного типа (Type). Есть два варианта использования. Первый — когда указывается номер конкретного интерфейса (Number), соответственно на выходе информация о нём. Второй — когда не указывается номер конкретного интерфейса, тогда на выходе результат всех интерфейсов этого типа. Если все активны, функция возвращает true, если хотя бы один не активен — false.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# Применение:
# $ifSta Type="vrrp" Number=2
# if ([$ifSta Type="vrrp"]=true) do={beep frequency=1760 length=100ms;}
# if ([$ifSta Type="vrrp" Number=2]=true) do={beep frequency=1760 length=100ms;}

:global ifSta do={
	set $Ia [/interface find type=$Type];
	set $Number [tonum $Number];
	set $Nm [len $Ia];
	do {
		if ([typeof $Number]="num") do={set $Nm $Number;} else={set $Nm ($Nm-1);}
		if ([/interface get number=($Ia->$Nm) running]=true) do={
			set $out true;
		} else={
			set $Nm 0;
			set $out false;
		}
	} while ($Nm>0 && [typeof $Number]!="num");
	return $out;
}

Включение/отключение интерфейсов по disabled статусу

Функция включает/отключает интерфейсы заданного типа (Type), все, либо конкретный по номеру (Number). Отслеживание состояния интерфейса происходит по статусу disabled. До изменения статуса интерфейса происходит ожидание (выполняется цикл). Переменная (Name) задаёт комментарий в лог-сообщени (имя скрипта использующего функцию).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# Применение:
# $ifDis Name="Имя скрипта" Type="vrrp" Disabled="no" - Включаем все VRRP интерфейсы;
# $ifDis Name="Имя скрипта" Type="pptp-out" Number=0 Disabled="no" - Включаем PPTP интерфейс номер 1;
# $ifDis Name="Имя скрипта" Type="l2tp-out" Number=1 Disabled="yes" - Выключаем L2TP интерфейс номер 2;

:global ifDis do={
	set $Ia [/interface find type=$Type];
	set $Sa {no=true;yes=false};
	set $Number [tonum $Number];
	set $Nm [len $Ia];
	do {
		if ([typeof $Number]="num") do={set $Nm $Number;} else={set $Nm ($Nm-1);}
		if ([/interface get number=($Ia->$Nm) disabled]=($Sa->$Disabled)) do={
			[/interface set number=($Ia->$Nm) disabled=$Disabled];
			do {delay 100ms;} while ([/interface get number=($Ia->$Nm) disabled]=($Sa->$Disabled));
			log info "$Name:: $Type interface $[/interface get number=($Ia->$Nm) name] disabled: $[/interface get number=($Ia->$Nm) disabled]";
			beep frequency=1760 length=10ms;
		}
	} while ($Nm>0 && [typeof $Number]!="num");
}

Включение/отключение интерфейсов по running статусу

Функция включает/отключает интерфейсы заданного типа (Type), все, либо конкретный по номеру (Number). Отслеживание состояния интерфейса происходит по статусу running. До изменения статуса интерфейса происходит ожидание (выполняется цикл). Переменная (Name) задаёт комментарий в лог-сообщени (имя скрипта использующего функцию). Дополнительно для VRRP-интерфейсов учитывается состояние backup, при котором не выполняется включение интерфейса, так как если он находится в состояние backup то он уже включен.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# Применение:
# $ifRun Name="Имя скрипта" Type="vrrp" Disabled="no" - Включаем все VRRP интерфейсы;
# $ifRun Name="Имя скрипта" Type="pptp-out" Number=0 Disabled="no" - Включаем PPTP интерфейс номер 1;
# $ifRun Name="Имя скрипта" Type="l2tp-out" Number=1 Disabled="yes" - Выключаем L2TP интерфейс номер 2;

:global ifRun do={
	set $Ia [/interface find type=$Type];
	set $Sa {no=false;yes=true};
	set $Number [tonum $Number];
	set $Nm [len $Ia];
	do {
		if ([typeof $Number]="num") do={set $Nm $Number;} else={set $Nm ($Nm-1);}
		if ($Disabled="yes" || [/interface vrrp get number=($Ia->$Nm) backup]!=true) do={
			if ([/interface get number=($Ia->$Nm) running]=($Sa->$Disabled)) do={
				[/interface set number=($Ia->$Nm) disabled=$Disabled];
				do {delay 100ms;} while ([/interface get number=($Ia->$Nm) running]=($Sa->$Disabled));
				log info "$Name:: $Type interface $[/interface get number=($Ia->$Nm) name] running: $[/interface get number=($Ia->$Nm) running]";
				beep frequency=1760 length=10ms;
			}
		}
	} while ($Nm>0 && [typeof $Number]!="num");
}

Удаление старых файлов

Функция находит файлы по полному или частичному имени (File) путём выборки по файлам и удаляет все файлы старше указанного периода (History), указывается в секундах минутах часах или днях (s/m/h/d). Алгоритм прост: если сегодняшняя дата, минус дата создания файла, больше чем заданный период, то файл удаляется. Переменная (Name) задаёт комментарий в лог-сообщени (имя скрипта использующего функцию).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# Применение:
# [$flDel File="Имя или часть имени файла" Name="Имя скрипта" History="7d"];

:global flDel do={
	:global foDte;
	:global cuDte;
 
	set $Cd ([$foDte Date=[$cuDte]]->0);
	set $Fa [/file find name~$File];
	set $Nm [len $Fa];
 
	set $Lt [pick $History ([len $History]-1) [len $History]];
	set $Dg [pick $History 0 ([len $History]-1)];
	set $Ta {s=1;m=60;h=3600;d=86400};
	set $Ht ($Dg*($Ta->$Lt)-10);
 
	do {
		set $Nm ($Nm-1);
		if ( ($Cd-([$foDte Date=[/file get number=($Fa->$Nm) value-name=creation-time]]->0))>$Ht ) do={
			log info "$Name:: Deleting old files: $([$foDte Date=[/file get number=($Fa->$Nm) value-name=creation-time]]->1)";
			/file remove number=($Fa->$Nm);
			beep frequency=1568 length=10ms;
			delay 100ms;
		} else={
			beep frequency=1975 length=10ms;
			delay 100ms;
		}
	} while ($Nm>0);
}

Создаёт папки в локальном хранилище при помощи FTP

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# Применение:
# $mkDir Address="IP на котором работает FTP" User="Имя пользователя" Password="Пароль" Input="Имя создаваемой директории, строкой или массивом" Name="Имя скрипта"
# Можно не указывать адрес, в этом случае будет использован первый из доступных IP на маршрутизаторе.
# $mkDir User="Имя пользователя" Password="Пароль" Input="Имя создаваемой директории, строкой или массивом" Name="Имя скрипта"
# $mkDir Address="172.16.0.1" User="user" Password="Passwd" Input=({"sync";"backup";"scripts";"log";"config"}) Name="scriptName"

:global mkDir do={
	set $Nm [len $Input];
	set $IP [/ip address get 1 address];
	/system identity export file=id.rsc
	if ([typeof $Address]="nothing") do={set $Address [pick $IP 0 [find $IP "/"]];}
 
	do {
		if ([typeof $Input]="array") do={set $Nm ($Nm-1);set $Bn ($Input->$Nm);} else={set $Nm 0;set $Bn $Input;}
		log info "$Name:: Start creating $Bn directory";
		set $Pth ($Bn . "/1");
		/tool fetch address=($Address) mode=ftp user=($User) password=($Password) 	src-path=id.rsc dst-path=($Pth)
		delay 3s;
		/file remove $Pth
		log info "$Name:: Done creating $Bn directory";
		beep frequency=1975 length=10ms;
		delay 1s;
	} while ($Nm>0 && [typeof $Input]="array");
}

Сохраняет конфигурации

Функция создаёт файлы конфигураций (*.rsc) в указанной директории (Path) для заданных функций маршрутизатора (Input). Переменная (Name) задаёт комментарий в лог-сообщени (имя скрипта использующего функцию). Используется для создания раздельных или комплексных бекапов системы в виде скриптов. Переменную (Input) можно задать как строкой, для точечного бекапа, так и массивом, для создания индивидуальных бекапов для каждой из перечисленных в массиве функций системы.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# Применение:
# $flCre Path="Диретория для записи" Input="Имя экспортируемого файла, строкой или массивом" Name="Имя скрипта"
# $flCre Path="disk1/script/" Input="system script" Name=$scriptName
# $flCre Path=$pathForConfigs Input=$configsArray Name=$scriptName
# $flCre Path=$pathForConfigs Input=({"ip route";"ip firewall";"ip pool";"ip dhcp-server";"interface"}) Name="scriptName"

:global flCre do={
	set $Nm [len $Input];
	do {
		if ([typeof $Input]="array") do={set $Nm ($Nm-1);set $Bn ($Input->$Nm);} else={set $Nm 0;set $Bn $Input;}
		log info "$Name:: Start creating $Bn file";
		execute "/$Bn export file=\"$Path$Bn\"";
		log info "$Name:: Done creating $Bn file";
		beep frequency=1975 length=10ms;
		delay 100ms;
	} while ($Nm>0 && [typeof $Input]="array");
}

Сохраняет экспорт файлы на FTP

Функция создаёт файлы конфигураций (*.rsc) в указанной директории (Path) для заданных функций маршрутизатора (Input) на маршрутизаторе^ затем отправляет их на указанный FTP сервер. Переменная (Name) задаёт комментарий в лог-сообщени (имя скрипта использующего функцию). Используется для создания раздельных или комплексных бекапов системы в виде скриптов. Переменную (Input) можно задать как строкой, для точечного бекапа, так и массивом, для создания индивидуальных бекапов для каждой из перечисленных в массиве функций системы. В качестве отчёта функция создаёт TXT файл с датой последнего экспорта. Данная функция не хранит историю и не удаляет старые файлы на FTP сервере перезаписывая их.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# Применение:
# $exSnd Path="Директория для записи" Input="Имя экспортируемого конфига, строкой или массивом" Prefix="Префикс имени файла" Address="IP удалённого сервера" User="Имя пользователя" Password="Пароль" Name="Имя скрипта"
# $exSnd Path="sync" Input={"ip pool";"ip dhcp-server";"interface vrrp"} Prefix="syncfile" Address="192.168.1.101" User="ftpuser" Password="ftppassword" Name="myscript"

:global exSnd do={
	set $Nm [len $Input];
	set $Nn "$Nm";
	if ([typeof $Prefix]="nothing") do={set $Prefix "syncfile";}
	do {
 
		if ([typeof $Input]="array") do={set $Nm ($Nm-1);set $Bn ($Input->$Nm);set $Bl ($Input->($Nm+1));} else={set $Nm 0;set $Bn $Input;}
 
		if ($Nm>-2) do={
			set $Fn "$Path/$Prefix-$Bl.rsc";
		} else={
			:global cuDte;
			:global foDte;
			set $Fn "$Path/$([$foDte Date=[$cuDte]]->1).synced";
			log info "$Name:: $Fn";
			set $Bl $Fn;
			[/file print without-paging value-list file=$Fn where name~$Prefix];
			:global flDel;
			[$flDel File="synced" Name=$Name History=10];
			set $Fn "$Fn.txt";
		}
 
		if ($Nm>-1) do={
			log info "$Name:: Start creating \"$Bn\" file";
			execute "/$Bn export file=\"$Path/$Prefix-$Bn.rsc\"";
			log info "$Name:: Done creating \"$Bn\" file";	
		}
 
		if ($Nm<($Nn-1)) do={
			log info "$Name:: Sending \"$Bl\" to remote device";
			/tool fetch address=$Address src-path=$Fn user=$User mode=ftp password=[:tostr $Password] dst-path=$Fn upload=yes;
			log info "$Name:: Sending \"$Bl\" to remote device complete";
		}
 
		beep frequency=1975 length=10ms;
		delay 100ms;
	} while ($Nm>-2 && [typeof $Input]="array");
}

Создаёт адрес листы для динамически созданных IP (dhcp-client, vpn, …)

Функция создаёт адрес листы для динамически созданных IP адресов. К таковым относятся полученные по DHCP адреса на всевозможных интерфейсах. Второй вариант использования предполагает поиск по фрагменту имени интерфейса и добавление его IP адреса в заданный адрес лист.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# Применение:
# $alSet Find="Имя или фрагмент имени интерфейса(ов)" List="Название адрес листа" Name="Имя скрипта"
# $alSet List="MyDynamicList" Name=$scriptName - Добавит все динамически созданные IP адреса в адрес лист "MyDynamicList"
# $alSet Find="uplink" List="MyUplinkList" Name=$scriptName - Добавит адреса всех интерфейсов, имя которых содержит "uplink" в адрес лист "MyUplinkList"

:global alSet do={
	if ([typeof $Find]="nothing") do={
		set $Ia [/ip address find dynamic];
	} else={
		set $Ia [/ip address find where actual-interface~$Find];
	}
 
	set $Nm [len $Ia];
 
	if ($Nm>0) do={
		do {
			set $Nm ($Nm-1);
			set $AI [/ip address get number=($Ia->$Nm) value-name=actual-interface];
			set $IP [/ip address get number=($Ia->$Nm) value-name=address];
			set $IP [pick $IP 0 [find $IP "/"]];
 
			if ([len [/ip firewall address-list find where address=$IP && list=$List]]=0) do={
				/ip firewall address-list add address=$IP comment=$AI list=$List
				log info "$Name:: Add interface \"$AI\" $IP to address list \"$List\"";
			}
 
		} while ($Nm>0);
		delay 500ms;
	}
 
	set $Ia [/ip firewall address-list find list=$List];
	set $Nm [len $Ia];
 
	if ($Nm>0) do={
		do {
			set $Nm ($Nm-1);
			set $AI [/ip firewall address-list get number=($Ia->$Nm) value-name=comment];
			set $IP [/ip firewall address-list get number=($Ia->$Nm) value-name=address];
 
			if ([len [/ip address find where address~"$IP/"]]=0) do={
				/ip firewall address-list remove numbers=($Ia->$Nm)
				log info "$Name:: Remove interface \"$AI\" $IP from address list \"$List\"";
			}
 
		} while ($Nm>0);
		delay 500ms;
	}
 
}

Контроллер

Контроллер работы скриптов и функций. Выполняется каждые 5 секунд при наличии скриптов «Edelweiss» и «Control» а так же глобальных переменных «controlledScripts» и «controlledFunctions». Следит за работой скриптов и при аварии перезапускает их. Так же будет полезен как некий аналог штатного планировщика для работы функций построенных на базе Edelweiss.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# Применение:
# $edelctl do=start
# $edelctl do=stop
# $edelctl do=restart
# $edelctl do=status

:global edelctl do={
 
	:local ecsrt do={
		if ([len [/system script job find where script=Edelweiss]]< 2) do={
			execute "/system script run Control";
			execute "/system script run Edelweiss";
		}
	}
 
	:local ecstp do={
		:global Edelweiss;
		set $Ia [/system script job find where script=Edelweiss];
		set $Nm [len $Ia];
		do {
			execute "/system script job remove numbers=$Ia"
			set $Nm ($Nm-1);
		} while ($Nm>0);
		log info "Edelweiss:: Stop \"Edelweiss Control\" $Edelweiss";
	}
 
	if ($do="start") do={$ecsrt;}
	if ($do="stop") do={$ecstp;}
	if ($do="restart") do={$ecstp;delay 500ms;$ecsrt;}
	if ($do="status") do={/system script job print where script=Edelweiss}
}
 
 
if ([len [/system script job find where script=Edelweiss]]< 2) do={
	if ([len [/system script find name=Control]]=1) do={
 
		:global Edelweiss;
		:global controlledScripts;
		:global controlledFunctions;
		if ([typeof $controlledScripts]="array" && [typeof $controlledFunctions]="array") do={
 
			log info "Edelweiss:: Start \"Edelweiss Control\" $Edelweiss";
 
			do {
 
				set $conA ([len $controlledScripts]-1);
				do {
					set $ScriptCurrentControl [($controlledScripts->$conA)];
					if ([len [/system script job find where script=$ScriptCurrentControl]]< 1 && [len [/system script find name=$ScriptCurrentControl]]=1) do={
						execute "/system script run $ScriptCurrentControl";
						log info "Edelweiss:: Run \"$ScriptCurrentControl\"";
					}
					delay 100ms;
					set $conA ($conA-1);
				} while ($conA>-1);
 
				set $conB ([len $controlledFunctions]-1);
				do {
					set $FunctionCurrentControl [($controlledFunctions->$conB)];
					execute "$FunctionCurrentControl Name=Edelweiss";
					delay 250ms;
					set $conB ($conB-1);
				} while ($conB>-1);
 
				delay 5s;
			} while (true);
 
		} else={
				execute "/system script run Control"
				delay 500ms;
				if ([typeof $controlledScripts]="array" && [typeof $controlledFunctions]="array") do={				
					log warning "Edelweiss:: Control variable not found. Restart script";
					execute "/system script run Edelweiss";
				} else={
					log warning "Edelweiss:: Control variable empty. Stop script";
					execute "$edelctl do=stop";
				}
			}
 
	} else={
		log warning "Edelweiss:: Script \"Control\" not found";
	}
 
}

Массив целей контроллера

Содержимое скрипта «Control». В данном примере Edelweiss будет каждые 5 секунд производить мониторинг работы скрипта «Failover» и выполнять функции «$alSet List=Dynamic» и «$alSet Find=uplink List=Uplink». Экранирование знака «$» обязательно, иначе он будет распознаваться как переменная до выполнения функции.

1
2
3
4
5
:global controlledScripts {"Failover";};
:global controlledFunctions {
	"\$alSet List=Dynamic";
	"\$alSet Find=uplink List=Uplink";
};

PS

Данна библиотека создана для упрощения использования скриптов в Router OS, их популяризации и расширения функциональности оборудования этого вендора в повседневной жизни. Все желающие присоединиться к разработке библиотеки могут присылать свои наработки и идеи мне на почту aleksov[a]set-pro.net

Узнать больше о том, как работают скрипты в MikroTik RouterOS можно у нашего коллеги Дмитрия Скромнова из русскоязычного онлайн-курса для самостоятельного изучения. Основанный на официальной программе MTCNA, зтот курс по MikroTik и RouterOS , содержит много полезной информации не вошедшей в MTCNA. Целых 162 видеоурока и большое практическое задание, разбитое на 45 лабораторных работ. Время на изучение неограниченно – все материалы передаются бессрочно и их можно пересматривать сколько нужно. Первые 25 уроков можно посмотреть бесплатно, оставив заявку на странице курса.

Библиотека функций для MikroTik RouterOS: 7 комментариев

  1. Очччень интересная мысль. Спасибо.
    Если не трудно, поправьте в статье в самом начале в списке объявляемых переменных вместо повторяющейся flDel последней должна быть flCre. И применение для переменной ifRun должно описывать действия с ней, а не с предыдущей ifDis.
    Спасибо вам огромное за то, что поделились в сети своими наработками.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Этот сайт использует Akismet для борьбы со спамом. Узнайте как обрабатываются ваши данные комментариев.