Community discussions

 
User avatar
lapsio
Member
Member
Topic Author
Posts: 472
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.
MTCNA, MTCRE, MTCINE

Who is online

Users browsing this forum: No registered users and 16 guests