Last active
January 29, 2020 23:05
-
-
Save samunders-core/11848bd7ecd9cd12d65e3041461136b2 to your computer and use it in GitHub Desktop.
OpenWRT/LEDE procd service to check/reconnect stalled/disconnected wan interface
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/sh /etc/rc.common | |
# https://joost.oostdijk.net/articles/service-configuration-with-procd/ | |
# runs until first stall/disconnect of recovery taking longer than 60 seconds | |
INTERNET_ADDRESS=8.8.8.8 | |
IFACE="${1:-LTE}" | |
SECONDS=${2:-10} | |
[ -z "${IFACE}" ] && { | |
/bin/echo -e "Usage: iface_watchdog <interface> [poll_each_seconds]\nChecks+reconnects stalled/disconnected interface" | /usr/bin/logger -s | |
exit 1 | |
} | |
USE_PROCD=1 | |
START=99 | |
SERVICE_DAEMONIZE=1 | |
SERVICE_WRITE_PID=1 | |
SERVICE_PID_FILE=/var/run/${IFACE}_watchdog.pid | |
SERVICE_QUIET=0 | |
STOP=10 | |
log() { | |
/usr/bin/logger -t WATCHDOG "$@" | |
} | |
start_service() { | |
log -s "Starting iface_watchdog ${IFACE} ${SECONDS}" | |
procd_open_instance "${IFACE}_watchdog" | |
procd_set_param command /bin/sh -c ". /etc/init.d/iface_watchdog ${IFACE} ${SECONDS}; watchdog" | |
procd_set_param respawn | |
procd_set_param pidfile "${SERVICE_PID_FILE}" | |
procd_close_instance | |
} | |
ppid() { # PID | |
/usr/bin/awk '{print $4}' < "/proc/$1/stat" | |
} | |
stop() { | |
DIR="$(/bin/pwd)" && cd /var/run | |
for pid in `/usr/bin/pgrep sleep`; do | |
ppid=`ppid $pid` | |
PID_FILE=`/bin/egrep -l "^$ppid"'$' *_watchdog.pid` && /usr/bin/tr '\0' '\n' < "/proc/$ppid/cmdline" | /bin/egrep -q "/etc/init.d/iface_watchdog\s${PID_FILE%%_watchdog.pid}" && { | |
log -s "Stopping iface_watchdog ${PID_FILE%%_watchdog.pid}" | |
/bin/kill $ppid $pid | |
/bin/sleep 1 | |
cd "$DIR" | |
return | |
} | |
done | |
cd "$DIR" | |
log -s 'WARNING: no matching process found, repeat your attempt!' | |
} | |
rxBytes() { # device | |
/bin/cat "/sys/class/net/$1/statistics/rx_bytes" | |
} | |
zeroBytesReceived() { # device | |
BYTES=`rxBytes "$1"` | |
DIFF=$((${BYTES} - ${RX_BYTES:-0})) | |
RX_BYTES=${BYTES} | |
return ${DIFF} | |
} | |
pause() { # seconds | |
/bin/sleep "$1" && return | |
/usr/bin/pgrep -qf 'iface_watchdog\sstop' && { | |
log "${IFACE}: Exit requested" | |
exit 0 | |
} | |
} | |
watchdog() { | |
. /lib/functions/network.sh | |
for sig in INT TERM ; do | |
trap "log '${IFACE}: Exiting on SIG$sig'; exit 0" $sig | |
done | |
log "${IFACE}: Started" | |
network_get_device DEV "${IFACE}" || [ -n "${DEV}" ] || { | |
log "${IFACE}: Unable to map to device, assuming boot => delaying reboot for 5 minutes" | |
pause 300 | |
network_flush_cache | |
} | |
while network_get_device DEV "${IFACE}" && [ -n "${DEV}" ] && [ `/sbin/logread | egrep -o 'lease of .* obtained, lease time.*' | uniq -c | awk 'END {print $1}'` -le 3 ]; do | |
zeroBytesReceived "${DEV}" && { | |
/bin/ping -c ${SECONDS} -w ${SECONDS} "${INTERNET_ADDRESS}" | |
zeroBytesReceived "${DEV}" && { | |
log "${IFACE}: Interface stalled at "`rxBytes "${DEV}"`" RX bytes, restarting device ${DEV}" | |
/usr/bin/env -i /sbin/ifup "${IFACE}" 2>&1 | /usr/bin/logger | |
log "${IFACE}: Waiting 60 seconds for device ${DEV} to come up" | |
pause $((60 - ${SECONDS})) | |
network_flush_cache | |
} | |
} | |
pause ${SECONDS} | |
done | |
log "${IFACE}: Unable to map to device, rebooting" | |
/sbin/reboot | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment