Persistent Environment Variables

search tag # rextended save and restore global variables on reboot

This is for save and restore variables with keeping the right data type on restore:

Scheduled script do that every x minutes, on purpose store only variables, but do not store codes or functions
because till now I do not have find one way to do that.
code = from “:parse” function, like :global c [:parse “/interface print”]
function = created like :global f do={ /interface print }, but is reported as array from :typeof

Only simple arrays are exported, do not work for array of array and more complex data structure.


/system script environment
:foreach item in=[find] do={
    :local vname  [get $item name]
    :local vvalue [get $item value]
    :if ($vvalue~"^\\*") do={:set vvalue "ID$vvalue"}
    :if ($vvalue~"^(\\(code\\)|;\?\\(eva\?l )") do={:set vvalue "(code)"}
    /ip firewall layer7
    remove [find where name=$vname]
    add name=$vname comment="$vvalue"
    :delay 10ms
    :execute "/ip firewall layer7 set [find where name=$vname] regexp=[:typeof \$$vname]"
    :if ($vvalue="(code)") do={:delay 10ms ; set [find where name=$vname] regexp="code"}
}

Store variable name… on name, variable type on regexp, variable contents on comment.


On reboot this script is scheduled at startup, this restore also variables that do not contain readable data, like binary data, lower numbers and special characters:

/ip firewall layer7
:foreach item in=[find where regexp~"^(array|bool|code|id|ip|ip-prefix|ip6|ip6-prefix|lookup|nil|nothing|num|str|time)\$"] do={
    :local vname  [get $item name]
    :local vvalue [get $item comment]
    :local vtype  [get $item regexp]
    /system script environment
    remove [find where name=$vname]
    :if ($vtype~"^(array|ip|ip6|num|str|time)\$") do={
        :execute ":global $vname [:to$vtype [/ip firewall layer7 get [find where name=$vname] comment]]"
    } else={
        :if ($vtype~"^(bool|id|ip-prefix|ip6-prefix|lookup|nil|nothing)\$") do={
            :if ($vtype="bool")         do={:execute ":global $vname [:tobool $vvalue]"}
            :if ($vtype="id")           do={:execute ":global $vname [:toid $[:pick $vvalue [:find $vvalue "*" -1] [:len $vvalue]]]"}
            :if (($vtype="ip-prefix") or \
                 ($vtype="ip6-prefix")) do={:execute ":global $vname [[:parse \":return $vvalue\"]]"}
            :if ($vtype="lookup")       do={:execute ":global $vname \"\$$vname\""}
            :if ($vtype="nil")          do={:execute ":global $vname"}
            :if ($vtype="nothing")      do={:execute ":global $vname [:nothing]"}
        } else={
            # vtype="code"
            :log error "Unknow variable >$vname< of type >$vtype<"
            :execute ":global $vname [/ip firewall layer7 get [find where name=$vname] comment]"
        }
    }
    :delay 10ms
}

True Level 7 rules for Firewall are not “touched” unless they regexp is exactly a single word as the names of reserved variable types.


Someone know the full list of variable types???

standard:
array
bool
id
ip
ip6
num
str
time

broken, but restored with an hack:
ip-prefix
ip6-prefix

not recoverable:
code
function (reported as array)

“undefined” types:
nil
nothing
lookup ($0 on functions)

The script is not fixed for unknow data types discovered from me on 2023:
https://forum.mikrotik.com/viewtopic.php?p=1014223#p1014223
apireq (api request)
exclamation
cmd
iterator
backreference

EDIT: added fix for new discovered “op” on RouterOS, thanks to @tabraham report

2025 EDIT: added missing types discovered on 2023