Script to improve netwatch, dynamic variable solution?

I’m trying to build a script to improve netwatch ability to notify downs on some VPN connections, those VPN connections are from SIM routers so I’m getting a lot of false downs while using netwatch (they disconnect for a while sometimes).

My idea is to create a script run by the scheduler that ping’s all the IP’s on /ppp secret tab, if the IP is down then a global variable ( counter unique for that host) is increased by 1, and if the IP is up then the counter goes back to 0. At the end, there’s an IF that checks if the counter is bigger than X and sends a notification. In my lack of understanding, I have not been able to implement that global “per-host variable” that I need. Since dynamic variables, or “variable in a variable” are not possible I’m stuck…

So far that’s the script I’ve written.

:local pingip
:log info "Script"

:foreach id in=[/ppp secret find where profile=SIMRouters ] do={
 :global $id_counter
 :local name [/ppp secret get $id name]
 :local address [/ppp secret get $id remote-address]
 :set pingip [/ping $address count=1]
 :if ($pingip = 0) do={
  :log info "Fail PING on $address $name"
  THERE SHOULD BE THE COUNTER + 1 #PSEUDOCODE
  IF COUNTER > X NOTIFY #PSEUDOCODE
 } else={
  log info "Ping OK on $address $name"
  COUNTER = 0 #PSEUDOCODE
 }
}

I’m missing a lot of knowledge so any advice would be really apreciated.

Just ask on MikroTik Forum…

:global arrayofvalues
:if ([:typeof $arrayofvalues] = "nothing") do={:set arrayofvalues [:toarray ""]}
/ppp secret
:foreach item in=[find where profile="SIMRouters"] do={
    :local pname  [get $item name]
    :local premip [get $item remote-address]
    :if ([:ping $premip count=1] != 1) do={
        :set ($arrayofvalues->$pname) (($arrayofvalues->$pname) + 1)
        :if (($arrayofvalues->$pname) = 5) do={
            :log error "Failed to PING 5 times on $premip $pname"
            # INSERT WARNING ROUTINE HERE
        }
    } else={
        :if (($arrayofvalues->$pname) >= 5) do={
            :log warning "PING succeeded again on $premip $pname"
            # INSERT UN-WARNING ROUTINE HERE
        }
        :set ($arrayofvalues->$pname) 0
    }
    :delay 1s
}

some suggestions:
do not use variable names than are like parameters (example name → pname)
everytime use the “:” like on :log, :set, :if, :ping etc.

if the operation is single and is easy understandeable:

:set pingip [/ping $address count=1]
:if ($pingip = 0) do={

better:

:if ([/ping $address count=1] = 0) do={



Commented version just for teaching

if exist I want use this variable

:global arrayofvalues

if it is not already defined, I defined it as empty Array

:if ([:typeof $arrayofvalues] = “nothing”) do={:set arrayofvalues [:toarray “”]}

I work only on that section

/ppp secret

select all items that have SIMRouters as profile

:foreach item in=[find where profile=“SIMRouters”] do={
:local pname [get $item name]
:local premip [get $item remote-address]
:if ([:ping $premip count=1] != 1) do={

if the ping fail, use the “username” as variable name and set it to “previous value + 1” (nothing + 1 = 1, no matter to set it first to 0)

    :set ($arrayofvalues->$pname) (($arrayofvalues->$pname) + 1)

I want be warned only one time, when the fail reach 5 times only

no matter is the 6th, 7th, 8th time, I want receive only one warning

    :if (($arrayofvalues->$pname) = 5) do={
        :log error "Failed to PING 5 times on $premip $pname"
        # INSERT WARNING ROUTINE HERE
    }
} else={

if I have been warned, I want be un-warned because the link work again

if before have failed only 4 thimes, and now is working, I do not want any warn (because I receive warning only the 5th time…)

    :if (($arrayofvalues->$pname) >= 5) do={
        :log warning "PING succeeded again on $premip $pname"
        # INSERT UN-WARNING ROUTINE HERE
    }

if ping successfully set / reset the variable to 0

    :set ($arrayofvalues->$pname) 0
}

prevent ping and CPU “storm”

:delay 1s

}

You may be interested in my script Notify on host up and down

rextended write

Perfect base for create better netwatch.
I start my own with idea of :local arrayofoperators {“WAN1 Orange GW”=192.168.1.1 ; “WAN2 ITSA GW”=192.168.2.2 } … but this is OT here.

What when we receive that:

put [typeof [ping 192.168.1.1 count=1]]
Columns: SEQ, HOST, SIZE, TTL, TIME, STATUS
SEQ HOST SIZE TTL TIME STATUS
0 37.109.59.29 84 64 1ms497us > net unreachable

nil

Probably better when main ([:ping $premip count=1] = 1) do={put “Only OK”} else={put “All timeout and nil results and other like no buffer space :D”}

EDIT: sorry, normal ros return 0 but my 7.1rc4 have bug what I describe it here: v7.1rc4 [development] is released! - #188 by SiB - RouterOS beta - MikroTik community forum ; workaround: count=3

I accept the hint, RouterOS 7 or not,
without move too much things, simply from “] = 0)” to “] != 1)”

:laughing:

PS: don’t get into the bad habit of omitting “:” before all the items where it should be put…

put [typeof [ping 192.168.1.1 count=1]]
# --->>
:put [:typeof [:ping 192.168.1.1 count=1]]

Thanks for teaching approach :slight_smile:

:put [:typeof [:ping 1.1.1.1 count=1]]
return nil at 7.1rc4 what is bug of course and a !=1 not help because even ping is OK then this nil exist and we have falsepossitive :).

if ( [:ping 1.1.1.1 count=1] != 1 ) do={put FailPing } else={put WorkingPing}
0 1.1.1.1 56 58 21ms998us
FailPing

PS. My WAN NetWatch works not and even have own up/down-scripts. This is perfect thread

in BUG environment simple logic like !=1 not work :slight_smile: counter=3 works and we wait for rc5

P.P.S: about the “!=” and “:”… the suggestions are for the syntax, not for fix the broken 7.1rc4 :frowning:


I do not want omit that the “original” question/idea is from @MrBonding
I just added my way to save “declared-later” variables…

Many, many thanks to you all especially for the brilliant response of @rextended, not only works flawlessly but also you’ve taken you time to explain and give really good advice about the script, I’m truly happy for your help. I do know now a little bit more about ROS thanks to you :slight_smile:

Many thanks!