Script Reboot On Connectivity Down

Hi everyone,
I’m trying to create a script that restarts my mikrotik when the connectivity status changes from up to down, if the connection is already down it shouldn’t restart. I tried with netwatch but since it starts as an “unknown” state when the state changes to “down” it goes into a reboot loop setting system reboot as script.
Anyone know how to help me?

Thanks very much.

Set global variable in startup script to any “non-unknown” state recognized by your script … eg. value 0.
Then let your script check line changes and if there are enough changes in some period reboot the device.
I use sth. like this

:global vDevPingArray
:local vTmpPingArray [:toarray ""]
:local vIP
:local vHostInfo
:local vTmpIP
:local vTmpHostInfo
:local vNil
:local vMailBody ""
:local vPingLimit 2

:set vPingLimit 2
#:log info "DEVPING START"
#
# add hosts which are in the DEVPING address list
#
:foreach vLease in=[/ip firewall address-list find where (list=DEVPING && !disabled) ] do={
  :set vIP ([/ip firewall address-list get $vLease address])
  :if ( ($vTmpPingArray->"$vIP")=nil) do={
    :set ($vTmpPingArray->"$vIP") { missed=0;\
                                                       lastseen;\
                                                       noping;\
                                                       upping;\
                                                       name="$[/ip firewall address-list get $vLease comment]"}
  }
}
#
# add hosts which are in the static DNS  table
#
:foreach vLease in=[/ip dns static find where !disabled ] do={
  :set vIP ([/ip dns static get $vLease address])
  :if ( ($vTmpPingArray->"$vIP")=nil) do={
    :set ($vTmpPingArray->"$vIP") { missed=0;\
                                                       lastseen;\
                                                       noping;\
                                                       upping;\
                                                       name="$[/ip dns static get $vLease name]"}
  }
}
#
# add hosts which are in the interface EOIP
#
:foreach vLease in=[/interface eoip find where !disabled ] do={
  :set vIP ([/interface eoip get $vLease remote-address])
  :if ( ($vTmpPingArray->"$vIP")=nil) do={
    :set ($vTmpPingArray->"$vIP") { missed=0;\
                                                       lastseen;\
                                                       noping;\
                                                       upping;\
                                                       name="$[/interface eoip get $vLease name]"}
  }
}
#
# add hosts which are in the interface IPIP
#
:foreach vLease in=[/interface ipip find where !disabled ] do={
  :set vIP ([/interface ipip get $vLease remote-address])
  :if ( ($vTmpPingArray->"$vIP")=nil) do={
    :set ($vTmpPingArray->"$vIP") { missed=0;\
                                                       lastseen;\
                                                       noping;\
                                                       upping;\
                                                       name="$[/interface ipip get $vLease name]"}
  }
}
#
# add hosts which are in the interface GRE
#
:foreach vLease in=[/interface gre find where !disabled ] do={
  :set vIP ([/interface gre get $vLease remote-address])
  :if ( ($vTmpPingArray->"$vIP")=nil) do={
    :set ($vTmpPingArray->"$vIP") { missed=0;\
                                                       lastseen;\
                                                       noping;\
                                                       upping;\
                                                       name="$[/interface gre get $vLease name]"}
  }
}
#
# update vTmpPingArray with data from current vDevPingArray
#
:foreach vTmpIP,vTmpHostInfo in=$vTmpPingArray do={
  :local vOldHostInfo ($vDevPingArray->"$vTmpIP")
  :if ( $vOldHostInfo!=nil) do={
# if host found in old table then copy old data. Check if name is the same
    :if ( ($vOldHostInfo->"name")!=($vTmpHostInfo->"name") ) do={
      :local vStateTxt (($vTmpHostInfo->"name") . " ($vTmpIP) changed name from " . ($vOldHostInfo->"name") . ".")
      :set vMailBody ($vStateTxt . "\n" . $vMailBody)
      :log warning  ("$vStateTxt" )  
    }
    :set ($vOldHostInfo->"name") ($vTmpHostInfo->"name")
    :set ($vTmpPingArray->"$vTmpIP") $vOldHostInfo
  }
}

:set vDevPingArray $vTmpPingArray

:foreach vIP,vHostInfo in=$vDevPingArray do={
  :if ([/ping $vIP count=1 interval=1s]=0) do={
    :set ($vHostInfo->"missed") (($vHostInfo->"missed")+1)
# no ping, first -> set change moment, following pings -> do nothing
#   missed=1 -> lastseen = do not touch = moment of last ping
#                noping = first miss moment
#   missed>1 -> do not touch anything
    :if ( ($vHostInfo->"missed")=1 ) do={
      :set ($vHostInfo->"noping") ([/system clock get date] . " at " . [/system clock get time])
    }
  } else={
# ping OK
#   always update lastseen...device still on-line or just appeared
    :set ($vHostInfo->"lastseen") ([/system clock get date] . " at " . [/system clock get time])
# the magic:
#   change missed to opposite sign
#	if device is online, no misses...just online the missed = 0 and operator does not change anything
#	if device was missing then missed becomes < 0
    :set ($vHostInfo->"missed") (-($vHostInfo->"missed"))
#   missed<-PingLimit -> ther was more than PingLimit consecutive misses so assume that we need to report it
#                   upping = lastessen
#   missed=0 -> do not nothing
    :if ( ($vHostInfo->"missed")<(-1*$vPingLimit)  ) do={
      :set ($vHostInfo->"upping") ($vHostInfo->"lastseen")
    }
  }
}
#
# Look for host which has changed state and report the change
#
:foreach vIP,vHostInfo in=$vDevPingArray do={
  :local missed ($vHostInfo->"missed")
  :local vState 0
  :if ( missed!=0 ) do={
# <0 - back on-line only if missed<-5
    :if ( missed<0 ) do={
      :if ( missed<-5 ) do={
        :set vState 1
      }
      :set ($vHostInfo->"missed") 0
    }
#
#   small feature: (missed > 5)  reports off-line each time,   (missed = 6) reports once
#
    :if ( missed=6 ) do={
      :set vState -1
    }
    :if ( $vState != 0 ) do={
      :local vStateTxt ""
      :set vStateTxt (($vDevPingArray->$vIP->"name") . " ($vIP) now ")	  
      if ( $vState=-1 ) do={
# down
        :set vStateTxt ($vStateTxt . "Offline.")
# add lastseen if only host had been ever seen - happens when we add device or after router startup 
        :if ( ($vDevPingArray->$vIP->"lastseen")!=nil) do={
               :set vStateTxt ($vStateTxt . " It was last seen on " . ($vDevPingArray->$vIP->"lastseen" . "."))
        }
        :log error  ("$vStateTxt" )
        :set vMailBody ($vStateTxt . "\n" . $vMailBody)
      } else={
#      up
        :set vStateTxt ($vStateTxt . "Online at " . ($vDevPingArray->$vIP->"upping") . ".")
# add noping if only host had been ever unseen - happens when we add device or after router startup 		
        :if ( ($vDevPingArray->$vIP->"noping")!=nil) do={
               :set vStateTxt ($vStateTxt . " It was offline since " . ($vDevPingArray->$vIP->"noping" . "."))
        }
        :log warning  ("$vStateTxt" )
        :set vMailBody ($vStateTxt . "\n" . $vMailBody)
      }
    }
  }
}
#
# send e-mail when is anything to send
#
:if ( ([:len $vMailBody])>0 ) do={
  [/tool e-mail send to=............ subject=("$[/system identity get name] @ $[/system clock get date] $[/system clock get time]") body=($vMailBody)]
}	
#:log info "DEVPING KONIEC"

Thanks BartoszP,
is it ok also using an lte dongle?

if the connection is already down it shouldn’t restart

If a grace period is acceptable, use the built in watchdog function:

https://help.mikrotik.com/docs/display/ROS/Watchdog

/system watchdog watch-address (IP; Default: )
The system will reboot, in case 6 sequential pings to the given IP address will fail. If set to none this feature is disabled. By default, the router will reboot every 6 minutes if the watch-address is set and not reachable.

Why not? Script does not care what kind of device it works on :slight_smile:
It’s not so simple but you can tailor it to your needs.

thanks nescafe2002,
but I need that if there is no connectivity the mikrotik does not restart. I tried to use watchdog but after 6 minutes it restarts.

could this kind of script work as logic?

var bool ConnWasUp == false;
while true;
if (ConnWasUp = true) then
if (connection down) then reboot;
sleep 2;
if (connection up) then ConnWasUp == True

I just need even a simpler script… Thanks :smiley:


BartoszP
do you know how to translate the following script to ros?

var bool ConnWasUp == false;
while true;
if (ConnWasUp = true) then
if (connection down) then reboot;
sleep 2;
if (connection up) then ConnWasUp == True

Thanks

Again, better use the built in watchdog function.

Enable / disable watchdog on startup:


/system scheduler add name=watchdog on-event=":delay 10\r\
    \n\r\
    \n:if ([/ping 1.1.1.1 count=4] = 0) do={\r\
    \n  /system watchdog set watch-address=0.0.0.0\r\
    \n} else={\r\
    \n  /system watchdog set watch-address=1.1.1.1\r\
    \n}" policy=read,write,test start-time=startup

…–––…

Thanks,
but if I want to run the check even when the mikrotik is already started?


You can add two scheduler entries, one on startup (unset watch-address) and another one to set the watch-address when there is connectivy. Not sure what problem you are trying to solve here?

Thank you,
the second scheduling to set the watch-address how can i do it?


/system scheduler add name=watchdog-disable on-event="/system watchdog set watch-address=none" policy=read,write,test start-time=startup

/system scheduler add interval=5m name=watchdog-enable on-event=":if ([/system watchdog get watch-address] = \"none\") do={:delay 2\r\
    \n  if ([/ping 1.1.1.1 count=4] != 0) do={\r\
    \n    /system watchdog set watch-address=1.1.1.1\r\
    \n  }\r\
    \n }" policy=read,write,test start-time=startup

Can I use these last two scripts is this correct? Do I even have to use the first one?