Community discussions

MikroTik App
 
User avatar
lapsio
Long time Member
Long time Member
Topic Author
Posts: 514
Joined: Wed Feb 24, 2016 5:19 pm

script error not caught by do: {} on-error

Thu Feb 07, 2019 5:58 pm

I have script for monitoring some network equipment but from time to time (once for several days/weeks) I'm getting error:
script,error ac: script error: no such item (4)
So I decided to add :do { ... } on-error do={ ... } construction around almost entire code but unfortunately I'm still getting that error and script still gets stuck (because it's stateful). Here's the code:
       :local addr
       :local pingNum
       :local fail
       :local failNum
       :local prevLastFail
       :local critical
       
       :local alarmLoud alarm1
       :local alarmSilent alarm2
       
       ###############################################
       
       :if ([:len [/system script environment find name="netwatch#nointr"]] = 0) do={ :global "netwatch#nointr" ; :set $"netwatch#nointr" false }
       :if ([:len [/system script environment find name="netwatch#lastfail"]] = 0) do={ :global "netwatch#lastfail" ; :set $"netwatch#lastfail" {-1} }                                       
       
       :global "netwatch#nointr"
       :global "netwatch#lastfail"
       
       :if ($"netwatch#nointr") do={
           :put "Intr active - aborting" 
       } else={
           :do {                                                                                                                                                                             
               :set "netwatch#nointr" true
               :set failNum 0
               :set prevLastFail $"netwatch#lastfail"
               :set "netwatch#lastfail" {-1}
               :set critical 0
       
               :if ([:len $prevLastFail] = 1) do={
                   :put "Last status: OK"                                                                                                                                                    
                   :if ([/system scheduler get [find name=netwatch] interval] != 00:00:10) do={                                                                                              
                       /system scheduler set [find name=netwatch] interval=00:00:10
                   }
               } else={                                                                                                                                                                      
                   /log info message="Last failures:"                                                                                                                                        
                   :put "Last failures"                                                                                                                                                      
                   :foreach fail in=$prevLastFail do={                                                                                                                                       
                       /log info message="Failed: $fail"                                                                                                                                     
                       :put "Failed: $fail"                                                                                                                                                  
                   }                                                                                                                                                                         
                   :if ([/system scheduler get [find name=netwatch] interval] != 00:00:01) do={                                                                                              
                       /system scheduler set [find name=netwatch] interval=00:00:01
                   }
               }                                                                                                                                                                             
       
       ###############################################
       
               :foreach hostPos in=[/ip firewall address-list find disabled=no list=watchAC address~"[0-9]+[.][0-9]+[.][0-9]+\$"] do={
                   :set addr [/ip firewall address-list get $hostPos address]                                                                                                                
                   :put "Checking $addr"                                                                                                                                                     
       
                   :set pingNum [:ping address=$addr count=1 interval=200ms]
                   :if ($pingNum = 0) do={                                                                                                                                                   
                       /log info message="Ping to $addr failed at first try"                                                                                                                 
                       :put "Ping to $addr failed at first try"                                                                                                                              
                       :delay delay-time=2s
       
                       :set pingNum [:ping address=$addr count=6]
                       :if ($pingNum=0) do={                                                                                                                                                 
                           /log info "Ping to $addr failed permanently"                                                                                                                      
                           :put "Ping to $addr failed permanently"
       
                           :if ([:len [/ip firewall address-list find disabled=no address=$addr list=watchQAC]] = 0) do={:set critical ($critical+1)}
       
                           :set failNum ($failNum+1)
                           :set ($"netwatch#lastfail"->$failNum) $addr
                       }
                   }
               }
               :set "netwatch#nointr" false
       
               :if ($failNum>0) do={
                   :put "Some machines are DOWN -- $"netwatch#lastfail""
                   if ($prevLastFail != $"netwatch#lastfail") do={
                       /log error "Some machines are DOWN -- $"netwatch#lastfail""
                   }
                   :if ($critical > 0) do={ /system script run $alarmLoud } else={/system script run $alarmSilent}
               }
               :if ($failNum=0 and $prevLastFail != $"netwatch#lastfail") do={
                   :put "All machines are back online"
                   /log warning "All machines are back online"
               }
           } on-error={
               :set "netwatch#nointr" false
               /log error "Netwatch error. Smooth recovery"
           }
       }
After error occurs netwatch#nointr variable is stuck on "true" preventing script from execution. So crash definitely occurs inside do {} on-error clause since variable is set tu true inside of it in the first place.

In case anyone wonders, it's probably not caused by dynamic entries in this line:
 :foreach hostPos in=[/ip firewall address-list find disabled=no list=watchAC address~"[0-9]+[.][0-9]+[.][0-9]+\$"] do={
since some of my routers don't have any DNS entries in this address list and still error occurs on them every so often.

Who is online

Users browsing this forum: No registered users and 61 guests