post_check: radio present but not beaconing (no ssid) is a warning, not ok

Adds classify_radio + hidden --classify-radio seam and check 13.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KqhjP7nud5gdBg25zCiRk9
This commit is contained in:
2026-09-23 17:35:33 -04:00
co-authored by Claude Sonnet 5
parent c4d9def8e3
commit 7333c1a1b3
2 changed files with 30 additions and 3 deletions
+21 -3
View File
@@ -8,6 +8,7 @@
# ./deploy.sh --post-check [conf] # read-only live checks (units, br0, LAN, NAT, dnsmasq, radios, uplink); exit 1 on any warning
# # POSTCHECK_WAIT=<s>: seconds retried probes may wait in total (default 15; 0 = single attempt)
# ./deploy.sh --classify-unit <ActiveState> <Result> <ExecMainStatus> # prints ok|finished|wait|warn (used by post_check; for tests)
# ./deploy.sh --classify-radio # reads `iw dev <if> info` text on stdin, prints beaconing|silent (no ssid line = silent; used by post_check; for tests)
# ./deploy.sh render <file> # preview a templated file on stdout
# ./deploy.sh --redact # filter stdin, masking secret values (used by --diff; for tests)
# Idempotent. Netplan (wlan0 + Starlink NIC = NM-managed WANs; eth0 is a LAN
@@ -141,6 +142,15 @@ classify_unit() { # classify_unit <ActiveState> <Result> <ExecMainStatus> -> ok
esac
}
classify_radio() { # stdin: `iw dev <if> info` text -> beaconing (has an ssid line) | silent
local line
while IFS= read -r line || [ -n "$line" ]; do
line=${line#"${line%%[![:space:]]*}"}
case "$line" in "ssid "*) echo beaconing; return 0 ;; esac
done
echo silent
}
post_check() { # read-only live checks; every probe is guarded, warns instead of aborting
set_units
echo "== post-deploy check =="
@@ -204,11 +214,16 @@ post_check() { # read-only live checks; every probe is guarded, warns instead o
has_dhcp() { local o; o=$(ss -ulnH 2>/dev/null | awk '{print $4}') || true; [[ $'\n'$o == *:67$'\n'* || $o == *:67 ]]; }
if retry has_dhcp; then echo " ok dnsmasq bound to UDP 67"
else warn "post-deploy: nothing bound to UDP port 67 (dnsmasq DHCP)"; fi
# f. AP radios
# f. AP radios (present but no ssid = hostapd is not beaconing)
radio_beaconing() { out=$(iw dev "$1" info 2>/dev/null) || return 1
[ "$(classify_radio <<<"$out")" = beaconing ]; }
for n in "$WIFI_5G_IFACE" "$WIFI_2G_IFACE"; do
if out=$(iw dev "$n" info 2>/dev/null); then
u=hostapd; [ "$n" = "$WIFI_5G_IFACE" ] || u=hostapd-2g
out=
if retry radio_beaconing "$n"; then
echo " ok radio $n: $(echo "$out" | grep -E 'ssid|channel' | sed 's/^[[:space:]]*//' | tr '\n' ';')"
else warn "post-deploy: radio $n not present (its hostapd keeps retrying until it appears)"; fi
elif [ -z "$out" ]; then warn "post-deploy: radio $n not present (its hostapd keeps retrying until it appears)"
else warn "post-deploy: radio $n is present but not beaconing (no ssid) — check: journalctl -u $u -n 30"; fi
done
# g. uplink
out=$(ip route show default 2>/dev/null) || true
@@ -265,6 +280,9 @@ case "${1:-}" in
--classify-unit) # ./deploy.sh --classify-unit <ActiveState> <Result> <ExecMainStatus>
classify_unit "${2:-}" "${3:-}" "${4:-}"
exit 0 ;;
--classify-radio) # ./deploy.sh --classify-radio < `iw dev <if> info` text
classify_radio
exit 0 ;;
--post-check) # ./deploy.sh --post-check [conf] — live checks, no root, no install; exit 1 on any warning
load_conf "${2:-$VANLINK_CONF}"
post_check