Scripting in the context of Netwatch

This script is called in Netwatch when DOWN or UP status changes.

I can’t figure out why this script fails if I un-comment any of the “:local” variable declarations:


:local myhost $host

/tool netwatch
#:local mystatus [get [find where host=$myhost] status]
#:local mycomment [get [find where host=$myhost] comment]
#:local myinterval [get [find where host=$myhost] interval]
#:local mytimeout [get [find where host=$myhost] timeout]
#:local mypacketinterval [get [find where host=$myhost] packet-interval]
#:local mypacketcount [get [find where host=$myhost] packet-count]
#:local mythrmax [get [find where host=$myhost] thr-max]
#:local mythravg [get [find where host=$myhost] thr-avg]
#:local mythrlosspercent [get [find where host=$myhost] thr-loss-percent]
#:local mythrlosscount [get [find where host=$myhost] thr-loss-count]
#:local mysince [get [find where host=$myhost] since]
#:local mypacketsize [get [find where host=$myhost] packet-size]

:log info "NETWATCH host=$myhost status=$mystatus comment=$mycomment interval=$myinterval timeout=$mytimeout packet-interval=$mypacketinterval packet-count=$mypacketcount thr-avg=$mythravg thr-loss-percent=$mythrlosspercent rttavg=$myrttavg"


:log info "NETWATCH Loss-Percentage=$"loss-percent""
:log info "NETWATCH rtt-avg=$"rtt-avg""
:log info "NETWATCH rtt-avg=$"thr-max""

Is actually

:local myhost $host

working? :confused:

or, what happens with:

{
:local myhost $host
:put $myhost
}
:local myhost $host

works just fine

“log info $myhost”

creates the correct log entry.

When I uncomment any of the commented :local statements an error is generated.

Can you just post the output of:

{
:local myhost $host
:put $myhost
}

Terminal output:

[admin@355hEX] > {
{... :local myhost $host
{... :put $myhost
{... }

[admin@355hEX] >

In the netwatch UP and DOWN entry: No output because, I believe, :put has no where to “put” it

In a script (with nothing else) called by the netwatch UP and DOWN entries: Also, no output.

The following as the script called by DOWN and UP in netwatch works fine:

:local myhost $host

:log info $myhost

/tool netwatch
#:local mystatus [get [find where host=$myhost] status]
#:local mycomment [get [find where host=$myhost] comment]
#:local myinterval [get [find where host=$myhost] interval]
#:local mytimeout [get [find where host=$myhost] timeout]
#:local mypacketinterval [get [find where host=$myhost] packet-interval]
#:local mypacketcount [get [find where host=$myhost] packet-count]
#:local mythrmax [get [find where host=$myhost] thr-max]
#:local mythravg [get [find where host=$myhost] thr-avg]
#:local mythrlosspercent [get [find where host=$myhost] thr-loss-percent]
#:local mythrlosscount [get [find where host=$myhost] thr-loss-count]
#:local mysince [get [find where host=$myhost] since]
#:local mypacketsize [get [find where host=$myhost] packet-size]

:log info "NETWATCH host=$myhost status=$mystatus comment=$mycomment interval=$myinterval timeout=$mytimeout packet-interval=$mypacketinterval packet-count=$mypacketcount thr-avg=$mythravg thr-loss-percent=$mythrlosspercent rttavg=$myrttavg"


:log info "NETWATCH Loss-Percentage=$"loss-percent""
:log info "NETWATCH rtt-avg=$"rtt-avg""
:log info "NETWATCH rtt-avg=$"thr-max""

Screenshot 2025-05-07 112259.png

Didn’t we already have this discussion about the same script?
See http://forum.mikrotik.com/t/netwatch-up-threshold/183422/1
It’s not helpful to start again, since context is lost.

Discussed in that thread is there is no need for :local variables in the first place! When a /system/script is called as action of /tool/netwatch up/down/test script, it will already have all the netwatch variables defined…
so all the :local that just do a find/get are unnecessary.

Also, the /system/script is marked as “Don’t Require Permissions”, correct?

If there is no output, I would suspect that $myhost is empty/not defined or not found.

Simple test:

{
:local myhost Pippo
:put $myhost
}

and/or:

/tool netwatch 
:local mystatus [get [find where host=] status]

does it give the same or a different error?

It’s a different problem.

And, my understanding is that only the rtt-* variables are predefined – not the thr-* variables. Is that not correct?

Yes, “Don’t Require Permissions” is checked.



[admin@355hEX] /tool/netwatch> {
{... :local myhost Pippo
{... :put $myhost
{... }
Pippo

And

[admin@355hEX] /tool/netwatch> :local mystatus [get [find where host=] status]
expected host value (line 1 column 39)

So, in the script, if you replace
:local myhost $host
with
:local myhost 8.8.8.8
(or whatever host you are using in the netwatch)
what happens?

Anyway, jaclaz has more patience than I. If we knew what the desired output and preferred scheme, it be easier to help.


Half true. The thr-* are not passed correct. But the variables passed on mostly right in docs https://help.mikrotik.com/docs/spaces/ROS/pages/8323208/Netwatch#Netwatch-Probestatistics%2Fvariables – with only the variable names for the ICMP specific probe statistics not be being corrected.

Still blank:

[admin@355hEX] /tool/netwatch> :local myhost 8.8.8.8
[admin@355hEX] /tool/netwatch> :put $myhost

[admin@355hEX] /tool/netwatch>

I tried this on multipl MT devices – same behavior.

Like a good portion of what I do, it’s mostly for learning.

In this case, I want to log the rtt-* values when Netwatch determines a DOWN situation so that I can tweak the thr-* values and come up with an overall combination threshold that works for me.

You need to use curly brackets when running commands in the terminal to keep everything in the same “scope”:

{
:local myhost 8.8.8.8
:put $myhost
}

Or:

{ :local myhost 8.8.8.8; :put $myhost }

Yep, “in the script” does not mean “in terminal”.
Curly brackets are needed (in terminal).

@Amm0
It’s not like I have more patience, more simply you are way more experienced and knowledgeable than I am in Mikrotik scripts, so you automatically give for reknown basic things that a beginner needs to learn, and the only way to learn is IMHO to try (and fail, and try again). I am pretty sure that Josephny after this will remember curly brackets and how “local” means “local”.

Now I get it.

Yes, :put output is now “8.8.8.8”

Thank you for your extreme patience and wise teaching skill.

Now back to why the :local commands in the script are causing an error…

I would try seeing what happens changing this:
:local mystatus [get [find where host=$myhost] status]
to:

:local mystatus [get [find where host=8.8.8
8] status]

(8.8.8.8 or whatever host Is your netwatch for)

My point is if you understand the problem, you MAY be able to avoid script. If goal is to JUST “tweak a netwatch”, then to output current values (rtt- loss- etc) AND configured “threshold”, the /system/logging topics=netwatch would do that. Not it’s not one line in logs, but so much easier than messing with any scripts… And, you can add a custom /system/logging/action just for netwatch to keep these netwatch debug items separate from main log. IMO that be a better approach for tweaking. Or if you want to get serious and track them, you can have the script append to file with CSV data to latter review in Excel.

If this is to learn scripting better… repeating the same get [find …] varname a bunch of times is inefficient. You can do ONE “get” without any attributes, and will return an array with all attributes. So as a learning exercise, it be better to learn arrays, which avoid needing so many locals. And there is a few videos on MiktoTik’s YouTube that fill in the blanks on array scripting usage more generally.

Thus you can use ONE local to get all the variables, then use array deconstruction to get particular values as needed (shown for CLI use … if using in /system/script the outer { } are NOT needed):

{
:local got [/tool/netwatch get [find host=8.8.8.8]]       
:log info "status $($got->"status") stdev $($got->"rtt-stdev") / $($got->"thr-stdev") max $($got->"rtt-max") / $($got->"thr-max") "
}

Also, what may be happening… is netwatch will not “get” a threshold value if it is still default value / left unset. (More specifically, the value return of the get will be type “nil”, and NOT the default value).