2db0d92d5a
Self-contained per-profile chrome log scanner with watermark-based new-match detection. Box CLI action returns JSON per-profile counts. Session: sidechat/chromebox-ops
82 lines
2.4 KiB
Bash
Executable File
82 lines
2.4 KiB
Bash
Executable File
#!/bin/bash
|
|
# chrome-error-scan.sh - scan per-profile chrome logs for concerning patterns.
|
|
# Self-contained: scans, compares against watermark, reports only NEW matches.
|
|
#
|
|
# Usage: chrome-error-scan.sh [--json]
|
|
# Default output: "profile:new_count" lines for profiles with new matches,
|
|
# or "OK: no new errors" if clean.
|
|
# --json: output JSON {"profile": {"total": N, "new": M}, ...}
|
|
#
|
|
# Watermark: /home/super/Projects/NetVM/chrome-error-watermark.json
|
|
# Patterns: FATAL, crash, segfault, out of memory (case-insensitive)
|
|
|
|
LOGDIR="/home/super/Projects/NetVM"
|
|
WATERMARK="$LOGDIR/chrome-error-watermark.json"
|
|
|
|
# Gather current counts per profile (grep -c prints 0 with exit 1 on no match;
|
|
# the || true masks the exit code while preserving the "0" on stdout)
|
|
get_count() {
|
|
local f="$LOGDIR/chromebox-$1.log"
|
|
if [ -f "$f" ]; then
|
|
grep -ciE "FATAL|crash|segfault|out of memory" "$f" 2>/dev/null || true
|
|
else
|
|
echo 0
|
|
fi
|
|
}
|
|
|
|
MUSE_C=$(get_count muse)
|
|
PIP_C=$(get_count pip)
|
|
N646_C=$(get_count 646)
|
|
OPM_C=$(get_count opm)
|
|
|
|
python3 - "$WATERMARK" "$MUSE_C" "$PIP_C" "$N646_C" "$OPM_C" "$1" <<'PYEOF'
|
|
import json, sys, os
|
|
|
|
watermark_path = sys.argv[1]
|
|
current = {
|
|
"muse": int(sys.argv[2]),
|
|
"pip": int(sys.argv[3]),
|
|
"646": int(sys.argv[4]),
|
|
"opm": int(sys.argv[5]),
|
|
}
|
|
as_json = len(sys.argv) > 6 and sys.argv[6] == "--json"
|
|
|
|
# Load watermark (tolerate missing/corrupt file -> treat as all-zero)
|
|
watermark = {}
|
|
if os.path.exists(watermark_path):
|
|
try:
|
|
with open(watermark_path) as f:
|
|
data = json.load(f)
|
|
watermark = data.get("counts", data) if isinstance(data, dict) else {}
|
|
except (ValueError, IOError, OSError):
|
|
watermark = {}
|
|
|
|
new_counts = {}
|
|
for prof in ("muse", "pip", "646", "opm"):
|
|
old = watermark.get(prof, 0)
|
|
try:
|
|
old = int(old)
|
|
except (TypeError, ValueError):
|
|
old = 0
|
|
delta = current[prof] - old
|
|
new_counts[prof] = max(delta, 0)
|
|
|
|
if as_json:
|
|
out = {p: {"total": current[p], "new": new_counts[p]} for p in current}
|
|
print(json.dumps(out))
|
|
else:
|
|
any_new = False
|
|
for prof in ("muse", "pip", "646", "opm"):
|
|
if new_counts[prof] > 0:
|
|
print("%s:%d" % (prof, new_counts[prof]))
|
|
any_new = True
|
|
if not any_new:
|
|
print("OK: no new errors")
|
|
|
|
# Update watermark atomically
|
|
tmp = watermark_path + ".tmp"
|
|
with open(tmp, "w") as f:
|
|
json.dump({"counts": current}, f, indent=2)
|
|
os.replace(tmp, watermark_path)
|
|
PYEOF
|