Я лишь оформил всё это дело в одну универсальную функцию.
Функция может сохранять глобальные переменные (кроме функций) в /ip firewall Layer7, который как нельзя более подходит для этой задачи. Сохраняются имена переменных (в именах записей), типы переменных (в комментариях), значения переменных - в значениях записей. Можно сохранять их с нужной переодичностью, вызывая функцию с параметром save из Планировщика. Восстановление происходит аналогично. При работе все записи Layer7, не относящиеся к данной задаче - НЕ ТРОГАЮТСЯ ! Можно также стирать все глобальные переменные из layer7 (другие записи при этом также НЕ СТИРАЮТСЯ !)
Можно печатать список переменных, хранящихся в layer7 на экран. Ниже код функции (первая версия):
Код: Выделить всё
#
# The function of saving/restoring global environment variables v 01/06/2022
# by Rextended (Rex) and Sertik https://forum.mikrotik.com/viewtopic.php?t=170591
# $1 parameter can take values:
# "save" - saving global variables in /ip firewall layer7
# "recover" - restoring global variables from layer7
# "erase" - cleaning layer7 only ! from global variables
# "print" - printing to the log and terminal of the list of variables located at the time of printing in Layer7
#
:global FuncGlobal do={
:if ([:typeof $0]="lookup") do={
:local count 0
:if (($1="save") or ($1="recover") or ($1="erase") or ($1="print")) do={
:if ($1="save") do={
/system script environment
:foreach item in=[find] do={
:local vname [get $item name]
:local vvalue [get $item value]
/ip firewall layer7
remove [find where name=$vname]
:if (([:typeof [:find [:tostr $vvalue] "(eval " -1]] = "nil") and ([:typeof [:find [:tostr $vvalue] "(evl " -1]] = "nil")) do={
:if ([:find $vvalue "*" -1] = 0) do={:set vvalue "ID$vvalue"}
add name=$vname regex="$vvalue"
:set count ($count+1)
}
:delay 10ms
:execute "/ip firewall layer7 set [find where name=$vname] comment=[:typeof \$$vname]"
}
:log warning ("Function $0 has saved $count variables")
:return $count}
:if ($1="recover") do={
/ip firewall layer7
:foreach item in=[find where comment~"^(array|bool|id|ip|ip-prefix|ip6|ip6-prefix|num|str|time|code|nothing|nil)\$"] do={
:set count ($count+1)
:local vname [get $item name]
:local vvalue [get $item regexp]
:local vtype [get $item comment]
# :if ($vvalue = "(function)") do={:set vtype "function" }
/system script environment
remove [find where name=$vname]
:if ($vtype~"^(array|bool|id|ip|ip6|num|str|time)\$") do={
:if ($vtype = "id") do={
:set vvalue [:pick $vvalue [:find $vvalue "*" -1] [:len $vvalue]]
:execute ":global $vname [:to$vtype $vvalue]"}
:if ($vtype = "bool") do={
[[:parse ":global $vname [:to$vtype $[/ip firewall layer7 get [find where name=$vname] regexp]]"]]
# :if ($vtype="bool") do={:execute ":global $vname [:tobool $vvalue]"}
} else={
:execute ":global $vname [:to$vtype [/ip firewall layer7 get [find where name=$vname] regexp]]"
}
} else={
:if ($vtype~"^(ip-prefix|ip6-prefix|nothing|nil)\$") do={
:if ($vtype~"^(ip-prefix|ip6-prefix)\$") do={:execute ":global $vname [[:parse \":return $vvalue\"]]"}
:if ($vtype="nothing") do={:execute ":global $vname [:nothing]"}
:if ($vtype="nil") do={:execute ":global $vname"}
} else={
:log error "Unknow variable type >$vtype<"
:execute ":global $vname [/ip firewall layer7 get [find where name=$vname] regexp]"
}
}
:delay 10ms;
}
:log warning ("Function $0 restored $count variables")
:return $count}
:if ($1="erase") do={
/ip firewall layer7
:foreach item in=[find where comment~"^(array|bool|id|ip|ip-prefix|ip6|ip6-prefix|num|str|time|code|nothing|nil)\$"] do={remove $item; :set count ($count+1)
}
:log warning ("The repository has been cleared of $count global variables")
:return $count}
:if ($1="print") do={
/ip firewall layer7
:foreach item in=[find where comment~"^(array|bool|id|ip|ip-prefix|ip6|ip6-prefix|num|str|time|code|nothing|nil)\$"] do={
:set count ($count+1)
:local vname [get $item name];
:local vvalue [get $item regexp];
:local vtype [get $item comment];
:put ("$vname "."$vtype "."$vvalue");
:log info ("$vname "."[ $vtype ] "."$vvalue");
}
:put ("In Layer7 repository has $count global variables")
:log warning ("In Layer7 repository has $count global variables")
:return $count}
} else={
:if ([:typeof $1]="nothing") do={:log error ("The function $0 parameter is not set"); :return ("Error $0")}}
:log error ("The function $0 parameter is not valid"); :return ("Error $0");
}
}
# usage examples:
# :log info [$FuncGlobal save]
# :log info [$FuncGlobal recover]
#:log info [$FuncGlobal erase]
# :log info [$FuncGlobal print]
# examples of erroneous usage:
# :log info [$FuncGlobal]
# :log info [$FuncGlobal anovertext]
:global FuncPersist do={
:local varName $1
:local varValue $2
:local varID [/ip firewall layer7-protocol find name="$varName"]
:if ([:typeof $varValue] = "nothing") do={
:if ($varID != "") do={
:set $varValue [/ip firewall layer7-protocol get $varID value-name=regexp]
}
} else={
:if ($varID = "") do={
/ip firewall layer7-protocol add name="$varName" regexp="$varValue" comment=[:typeof $varName]
} else={
/ip firewall layer7-protocol set $varID regexp="$varValue"
}
}
return $varValue
}
# Usage examples: (name = variable name, value = variable value)
# [$FuncPersist name] = Read persistent variable
# [$FuncPersist name value] = Write persistent variable
# :global name [$FuncPersist name] = Read persistent variable and write it to a global variable
# :global name [$FuncPersist name value] = Write data into a global variable and into a persistent variable at the same time
# Notes:
# The function uses layer7-protocols to store persistent data.
# All data read from persistent storage will be strings.
# The function always returns a value.