Skip to content

Instantly share code, notes, and snippets.

@wudi
Last active September 14, 2026 15:07
Show Gist options
  • Select an option

  • Save wudi/083c0be0286b5da300021dba727bf586 to your computer and use it in GitHub Desktop.

Select an option

Save wudi/083c0be0286b5da300021dba727bf586 to your computer and use it in GitHub Desktop.
Netgear R8500 路由器 OpenWRT 5G信号 看门狗
#!/bin/sh
# Restart R8500 5 GHz APs after brcmfmac firmware crash.
# radio0 = NETGEAR_5G-2 (phy0), radio2 = NETGEAR_5G-1 (phy2)
LOCK=/var/run/wifi5-watchdog.lock
STATE_DIR=/tmp/wifi5-watchdog
RESTART_LOG=$STATE_DIR/restarts
MAX_RESTARTS_PER_HOUR=6
MISS_NEEDED=2
COOLDOWN_SEC=90
TAG=wifi5-watchdog
mkdir -p "$STATE_DIR"
if ! lock -n "$LOCK" 2>/dev/null; then
exit 0
fi
trap 'lock -u "$LOCK" 2>/dev/null' EXIT
now=$(date +%s)
if [ -f "$STATE_DIR/cooldown" ]; then
cool=$(cat "$STATE_DIR/cooldown" 2>/dev/null)
if [ -n "$cool" ] && [ $((now - cool)) -lt "$COOLDOWN_SEC" ]; then
exit 0
fi
fi
iface_is_ap() {
iw dev "$1" info 2>/dev/null | grep -q "type AP"
}
radio_enabled() {
[ "$(uci -q get "wireless.${1}.disabled")" != "1" ]
}
prune_restarts() {
[ -f "$RESTART_LOG" ] || return 0
awk -v now="$now" '$1 >= now-3600 { print }' "$RESTART_LOG" > "$RESTART_LOG.tmp"
mv "$RESTART_LOG.tmp" "$RESTART_LOG"
}
too_many_restarts() {
prune_restarts
count=$(wc -l < "$RESTART_LOG" 2>/dev/null || echo 0)
[ "$count" -ge "$MAX_RESTARTS_PER_HOUR" ]
}
record_restart() {
echo "$now" >> "$RESTART_LOG"
echo "$now" > "$STATE_DIR/cooldown"
}
restart_radio() {
radio=$1
sta_guess=$2
if too_many_restarts; then
logger -t "$TAG" "skip $radio: more than $MAX_RESTARTS_PER_HOUR restarts in 1h"
return 1
fi
logger -t "$TAG" "restarting $radio (5 GHz AP missing after firmware crash)"
ip link del "$sta_guess" 2>/dev/null
wifi down "$radio"
sleep 2
wifi up "$radio"
record_restart
}
check_radio() {
radio=$1
expect_if=$2
sta_guess=$3
miss_file="$STATE_DIR/${radio}.miss"
radio_enabled "$radio" || {
rm -f "$miss_file"
return 0
}
ifname=$(ubus call network.wireless status 2>/dev/null | jsonfilter -e "@.${radio}.interfaces[0].ifname")
[ -n "$ifname" ] || ifname=$expect_if
if iface_is_ap "$ifname" || iface_is_ap "$expect_if"; then
rm -f "$miss_file"
return 0
fi
miss=$(cat "$miss_file" 2>/dev/null || echo 0)
miss=$((miss + 1))
echo "$miss" > "$miss_file"
logger -t "$TAG" "$radio AP down ($ifname missing), miss=$miss/$MISS_NEEDED"
if [ "$miss" -ge "$MISS_NEEDED" ]; then
restart_radio "$radio" "$sta_guess"
rm -f "$miss_file"
fi
}
check_radio radio0 phy0-ap0 wlan0
check_radio radio2 phy2-ap0 wlan1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment