Skip to content

Instantly share code, notes, and snippets.

@samunders-core
Last active January 29, 2020 23:05
Show Gist options
  • Save samunders-core/11848bd7ecd9cd12d65e3041461136b2 to your computer and use it in GitHub Desktop.
Save samunders-core/11848bd7ecd9cd12d65e3041461136b2 to your computer and use it in GitHub Desktop.
OpenWRT/LEDE procd service to check/reconnect stalled/disconnected wan interface
#!/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