Running a script from Netwatch doesn't work

I am aware that Netwatch UP/Down/Test scripts do not work with global variables and that it can only run scripts with the “read, write, test and reboot” policies, I have created a Netwatch task and a system script.

Netwatch Task

/tool netwatch
add disabled=no down-script=":log warning \"Wireguard to house is down\"" \
    host=172.17.60.2 http-codes="" interval=1m name=house test-script="" \
    timeout=1s type=simple up-script="/system script run lastSendToZero"

Script “lastSendToZero”

/system script
add dont-require-permissions=no name=lastSendToZero owner=admin \
    policy=reboot,read,write,test source=":global tgFunc\r\
    \n:global lastSend\r\
    \n:local deviceName [/system identity get name]\r\
    \n\$tgFunc (\"\\E2\\9C\\85 \$deviceName: Wireguard to house is UP\")\
    \r\
    \n:log warning \"Wireguard to house is UP\"\r\
    \n:delay 1s\r\
    \n:set lastSend 0"

The variable “lastSend” in the Environment tab should change to the value of “0” (its initial value is “1”) and it does not change, however the warning message in the log “Wireguard to house is UP” does work.

I don’t understand, where is the problem?

see next post

I tried it, it doesn't work either

Thx.

Each user has it’s own environment, no matter of policy,
each run of netwatch script have it’s own environment, no matter of policy

Notice: >>>probably is fixed on some new RouterOS version<<<


/system script
add dont-require-permissions=no name=testScript owner=admin policy=reboot,read,write,test source=\
    ":log info \"Script Start: >\$lastSend<\"\r\
    \n:global lastSend \"SCRIPT\"\r\
    \n:log info \"Script End:>\$lastSend<\""

/tool netwatch
add disabled=no down-script=":log info \"Down Start: >\$lastSend<\"\r\
    \n:global lastSend \"DOWN\"\r\
    \n:log info \"Down End:>\$lastSend<\"\r\
    \n/sys script run testScript" host=127.0.0.1 http-codes="" test-script=":log info \"Test Start: >\$lastSend<\"\r\
    \n:global lastSend \"TEST\"\r\
    \n:log info \"Test End:>\$lastSend<\"\r\
    \n/sys script run testScript" type=simple up-script=":log info \"Up Start: >\$lastSend<\"\r\
    \n:global lastSend \"UP\"\r\
    \n:log info \"Upt End:>\$lastSend<\"\r\
    \n/sys script run testScript"

set dont-require-permissions to yes only allow you on script to do things forbidden by netwatch policy, but you still can not interact with “global” variables.


To circumvent this, use layer 7 firewall for store variables…
On this way simply variables survive on reboots. Too much complex variables or functions on reboot are ruined and must be re-setted.


/ip firewall layer7-protocol
add name=lastSend regexp="TEST"

/system script
add dont-require-permissions=no name=testScript owner=admin policy=reboot,read,write,test \
    source=":local lastSend [/ip firewall \
    layer7-protocol get [find where name=lastSend] regexp]\r\
    \n:log info \"Script Start: >\$lastSend<\"\r\
    \n\r\
    \n/ip firewall layer7-protocol set [find where name=lastSend] regex=\"SCRIPT\"\r\
    \n\r\
    \n:local lastSend [/ip firewall layer7-protocol get [find where name=lastSend] regexp]\r\
    \n:log info \"Script End:>\$lastSend<\""

/tool netwatch
add disabled=no down-script=":local lastSend [/ip firewall layer7-protocol get [find where name=lastSend] regexp]\r\
    \n:log info \"Down Start: >\$lastSend<\"\r\
    \n\r\
    \n/ip firewall layer7-protocol set [find where name=lastSend] regex=\"DOWN\"\r\
    \n\r\
    \n/sys script run testScript\r\
    \n\r\
    \n:local lastSend [/ip firewall layer7-protocol get [find where name=lastSend] regexp]\r\
    \n:log info \"Down End: >\$lastSend<\"\r\
    \n" host=127.0.0.1 http-codes="" test-script="" type=simple up-script=":local lastSend [/ip firewall layer7-protocol get [fi\
    nd where name=lastSend] regexp]\r\
    \n:log info \"Up Start: >\$lastSend<\"\r\
    \n\r\
    \n/ip firewall layer7-protocol set [find where name=lastSend] regex=\"UP\"\r\
    \n\r\
    \n/sys script run testScript\r\
    \n\r\
    \n:local lastSend [/ip firewall layer7-protocol get [find where name=lastSend] regexp]\r\
    \n:log info \"Up End: >\$lastSend<\""

OK, thanks Rex
Molto cordiali.

PS: I do not understand how after so many years Mikrotik has not solved the problem of a “super-admin” user not being able to work with global variables or execute scripts from Netwatch or from the DHCP Client/Server. Too bad.

The problem is the misleading name: “global” is a user session.

ideal => actual
:global => , but a file content in store, json, or parameters in layer7 and similar can be used for store simple values.
=> :global
=> :local at the script start
:local => :local

Hi Rex

I have already tested your solution and it works very well, indeed it is not necessary a global variable in some cases.

In Netwatch as well as in a system script both commands work well, it allows you to save/retrieve the data in any situation.


ip firewall layer7-protocol set [find where name=lastSend] regex="any_data"
:local lastSend [/ip firewall layer7-protocol get [find where name=lastSend] regexp]

If I may suggest, this idea could go to your “Rextended Fragments of Snippets” thread, it could help many people who always ask the same question (until Mikroltik implements a way to change policies or rights in Netwatch).

Thanks again master!

When variables are stored in such way (like layer7) data is persisted after reboot, while for variables defined as :global is not. When data is stored in ROS config it is stored on disk which rises sector writes, this can be issue if is frequently written, depends on case. To behave as :global, alternative is to create tmpfs mount at some path and store/read variable data in file at tmpfs path, it will be stored on RAM and lost after reboot.

Possibly a stupid idea :open_mouth: , but would it be possible to generate a log entry with the variable and its value and then parse it out from the log? :question:
The log is usually volatile (in ram, doesn’t survive reboot), isn’t it?

Yes, but It seems more complicated and bloats log, also log has limit so there is a chance that record can be lost for reading. ROS config is easy to create for tmpfs mount, eg. to create on /tmp path:

/disk add media-interface=none media-sharing=no slot=tmp tmpfs-max-size=1M type=tmpfs

Files stored to /tmp will not be stored on disk and persisted, mount will because it is ROS config, just directory will be empty after reboot.

P.S.
For devices with flash disk this unnecessary because files stored outside /flash mount (and not in other slot dir for mounted disk) will be also stored in RAM and lost after reboot.

Thanks for the tip @optio.
Can you give an example of how to read/write a value in that drive?

As any other file in some directory, for tmpfs and other mounts without partitions directory where drive is mounted is named by slot name - if slot=tmp, directory is /tmp

:local readFile do={
  :if ([/file find name=$1]) do={
    :return [/file get $1 contents]
  }
  :return [:nothing]
}

:local writeFile do={
  :if ([/file find name=$1]) do={
    /file set $1 contents=$2
  } else={
    /file add name=$1 contents=$2
  }
}

# don't put leading / in file path
:local filepath "tmp/example.txt"

$writeFile $filepath "something"
:local fileData [$readFile $filepath]
:put $fileData

can be saved also as json…


On some way is already present…
http://forum.mikrotik.com/t/rextended-fragments-of-snippets/151033/1

Now with v7 better use also serialize/deserialize with json

duplicate

Yes, I have tried (for academic purposes) the possibility of using JSON from Netwatch, but I have had no luck, if I try to write (:serialize) from a Netwatch script window, I get the typical error: “executing script from netwatch failed, please check it manually”.

Netwatch:

/file/add name=lastSend.json contents=[:serialize to=json {"lastSend"="off"}]

I have also tried to execute from Netwatch a system script with its own policies: “read, write, reboot and test” with the same content, but it insists in the error.

Netwatch:

/sys scr run script-test

script-test

/file/add name=lastSend.json contents=[:serialize to=json {"lastSend"="off"}]

Outside Netwatch, everything works fine.