Full verification of the skill against Cascades (live): - All 19 scripts syntax-clean. - Controller-side read-only validated live: sites, audit-site, switch-audit, live-stats, model-rank, optimize-radios, monitor-run, gw-audit. Dry-run apply paths validated: apply-radio, apply-wlan, client-control, device-control. AP-side mechanism validated: SSH auth + /proc/ui_neighbor read on a sample AP; full neighbor-collect (74-AP SNR sweep) -> channel-plan end-to-end produced a 1/6/11 plan. Fixes: - optimize-radios.sh: the `for(k in prof)` loop's numeric completion value was REPL-echoed by the legacy mongo shell (stray "94.56..." line in output). Terminated the loop body with `void 0` to suppress it. - ASCII-clean printed output (CLAUDE.md no-non-ASCII): replaced em-dashes / Unicode arrows / § that reached stdout and rendered as `?`/mojibake on the Windows console, across optimize-radios, neighbor-collect, survey-collect, dfs-check, audit-site, sites, monitor-run, apply-radio, apply-wlan, pfsense-backend. (Comment-only non-ASCII left as-is; never printed.) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
45 lines
2.5 KiB
Bash
45 lines
2.5 KiB
Bash
#!/usr/bin/env bash
|
|
# monitor-run.sh — scheduled fleet/site health sweep. Runs the CONTROLLER-SIDE audits (no AP cred /
|
|
# VPN needed) and prints a compact per-site digest of flags only, so it's cron-friendly for ongoing
|
|
# monitoring of every client we manage. Pure read-only.
|
|
# per site -> gw-audit flags (WAN/internet/disconnected/pending/firmware) + switch-audit flags
|
|
# (underspeed/PoE/errors/offline) + audit-site WiFi flag count.
|
|
#
|
|
# Usage:
|
|
# bash .claude/skills/unifi-wifi/scripts/monitor-run.sh <site-name|id> # one site
|
|
# bash .claude/skills/unifi-wifi/scripts/monitor-run.sh all # every UOS site (slow)
|
|
# Cron example (nightly digest): 0 6 * * * bash .../monitor-run.sh all >> /var/log/unifi-monitor.log 2>&1
|
|
set -uo pipefail
|
|
REPO="$(git rev-parse --show-toplevel 2>/dev/null || echo .)"
|
|
UOS="$REPO/.claude/scripts/uos-mongo.sh"; D="$REPO/.claude/skills/unifi-wifi/scripts"
|
|
ARG="${1:?usage: monitor-run.sh <site|all>}"
|
|
clean(){ grep -viE 'post-quantum|store now|upgraded|openssh.com|WARNING: connection'; }
|
|
|
|
sweep_one(){ # $1 = site id, $2 = display name
|
|
local sid="$1" nm="$2"
|
|
echo "================================================================"
|
|
echo "SITE: ${nm:-$sid} ($sid)"
|
|
# gateway/WAN/health flags
|
|
local g; g="$(bash "$D/gw-audit.sh" "$sid" 2>&1 | clean | sed -n '/^== FLAGS/,$p' | grep -E '^\s*\[' )"
|
|
echo " gateway/health:"; [ -n "$g" ] && echo "$g" | sed 's/^/ /' || echo " [OK]"
|
|
# switch/PoE flags (summary line + any flags)
|
|
local sflag; sflag="$(bash "$D/switch-audit.sh" "$sid" 2>&1 | clean | grep -E 'UNDERSPEED|ERRORS|DROPS|POE-|OFFLINE|flag\(s\)' )"
|
|
echo " switches:"; [ -n "$sflag" ] && echo "$sflag" | sed 's/^/ /' | head -20 || echo " [OK] no switches / no issues"
|
|
# wifi config flag count
|
|
local wc; wc="$(bash "$D/audit-site.sh" "$sid" 2>&1 | clean | grep -cE '^\s*\[!\]' )"
|
|
echo " wifi config flags: ${wc:-0}"
|
|
}
|
|
|
|
if [ "$ARG" = all ]; then
|
|
echo "[INFO] fleet health sweep - $(date '+%Y-%m-%d %H:%M') - all UOS sites (controller-side, read-only)"
|
|
bash "$UOS" --sites 2>/dev/null | clean | grep -E '^[0-9a-f]{24}' | while read -r sid rest; do
|
|
sweep_one "$sid" "$rest"
|
|
done
|
|
else
|
|
if [[ "$ARG" =~ ^[0-9a-f]{24}$ ]]; then SID="$ARG"; NM=""; else
|
|
line="$(bash "$UOS" --sites 2>/dev/null | clean | grep -i "$ARG" | head -1)"; SID="${line%% *}"; NM="${line#* }"; fi
|
|
[ -n "$SID" ] || { echo "[ERROR] site not found: $ARG"; exit 1; }
|
|
echo "[INFO] health sweep - $(date '+%Y-%m-%d %H:%M') - $NM"
|
|
sweep_one "$SID" "$NM"
|
|
fi
|