#!/bin/sh /etc/rc.common START=01 PIDFILE="/tmp/run/watchcat" append_string() { local varname="$1"; local actual="${!varname}"; local add="$2"; local separator="${3:- }" new="${actual:+$actual$separator}$add" eval "$varname=\$new" } shutdown_now() { local forcedelay="$1" reboot & [ "$forcedelay" -ge 1 ] && { sleep $forcedelay echo b > /proc/sysrq-trigger # Will immediately reboot the system without syncing or unmounting your disks. } } watchcat_allways() { local period="$1"; local forcedelay="$2" sleep $period && shutdown_now "$forcedelay" } watchcat_ping() { local period="$1"; local forcedelay="$2"; local pinghosts="$3"; local pingperiod="$4" time=$(cat /proc/uptime) && time=${time%%.*} last=$time while true do sleep $pingperiod time=$(cat /proc/uptime) && time=${time%%.*} for host in "$pinghosts" do if ping -c 1 "$host" &> /dev/null then last=$time else diff=$((time-last)) logger -p daemon.info -t "watchcat[$$]" "no internet connectivity for $diff seconds. Reseting when reaching $period" fi done diff=$((time-last)) [ $diff -ge $period ] && shutdown_now "$forcedelay" done } timetoseconds() { local time=$1 unset seconds { [ "$time" -ge 1 ] 2> /dev/null && seconds="$time"; } || \ { [ "${time%s}" -ge 1 ] 2> /dev/null && seconds="${time%s}"; } || \ { [ "${time%m}" -ge 1 ] 2> /dev/null && seconds=$((${time%m}*60)); } || \ { [ "${time%h}" -ge 1 ] 2> /dev/null && seconds=$((${time%h}*3600)); } || \ { [ "${time%d}" -ge 1 ] 2> /dev/null && seconds=$((${time%d}*86400)); } } load_watchcat() { config_get period $1 period config_get mode $1 mode "allways" config_get pinghosts $1 pinghosts "8.8.8.8" config_get pingperiod $1 pingperiod "600" config_get forcedelay $1 forcedelay "0" error="" timetoseconds "$period" period="$seconds" [ "$period" -ge 1 ] \ || append_string "error" "period is not set or not recognized" "; " [ "$mode" = "allways" -o "$mode" = "ping" ] \ || append_string "error" "mode must be 'allways' or 'ping'" "; " [ -n "$pinghosts" -o "$mode" = "allways" ] \ || append_string "error" "pinghosts must be set in 'ping' mode" "; " timetoseconds "$pingperiod" pingperiod="$seconds" [ "$pingperiod" -l "$period" -o "$mode" = "allways" ] \ || append_string "error" "pingperiod is not recognized" "; " [ "$forcedelay" -ge 0 ] \ || append_string "error" "forcedelay must be a integer greater or equal than 0, where 0 means disabled" "; " [ -n "$error" ] && { logger -p user.err -t "watchcat" "reboot program $1 not started - $error"; return; } if [ "$mode" = "allways" ] then watchcat_allways "$period" "$forcedelay" & else watchcat_ping "$period" "$forcedelay" "$pinghosts" "$pingperiod" & fi echo $! >> "$PIDFILE".pids logger -p user.info -t "sshtunnel" "started tunnels to $server (pid=$!;retrydelay=$retrydelay)" } stop() { if [ -f "$PIDFILE".pids ] then logger -p user.info -t "watchcat" "stopping all reboot programs" while read pid do kill $pid done < "$PIDFILE".pids rm "$PIDFILE".pids logger -p user.info -t "watchcat" "all reboot programs stopped" else logger -p user.info -t "watchcat" "no reboot programs running" fi } start() { [ -f "$PIDFILE".pids ] && stop config_load system if [ -n "$(uci show system.@watchcat[0])" ] # at least one watchcat section exists then logger -p user.info -t "watchcat" "starting all reboot programs" config_foreach load_watchcat watchcat logger -p user.info -t "watchcat" "all reboot programs started" else logger -p user.info -t "watchcat" "no reboot programs defined" fi }