Initial cross-server log inventory + anomaly scan
- 10 hosts (mo1, ams, ams2, ro1, ca1, ca2, ca3, fr1, sony, termux) - discover-logs.sh: portable inventory (Linux/FreeBSD/Termux) - scan-anomalies.sh: ERROR/WARN/CRITICAL counts + journalctl + kubectl - run-all.sh: parallel SSH fan-out - build-summary.py: aggregates into reports/SUMMARY.md - 5 HIGH-severity findings identified on ro1 (apache scanner traffic, mount_monitor warnings)
This commit is contained in:
72
scripts/scan-anomalies.sh
Executable file
72
scripts/scan-anomalies.sh
Executable file
@@ -0,0 +1,72 @@
|
||||
#!/bin/sh
|
||||
# scan-anomalies.sh — inspect recent log files for error/warning/critical patterns.
|
||||
# Output is human-readable; one block per file with issues.
|
||||
|
||||
set -u
|
||||
HOST=$(hostname 2>/dev/null || uname -n)
|
||||
echo "=== Anomaly scan: $HOST ($(date -u +%FT%TZ)) ==="
|
||||
echo
|
||||
|
||||
# 1. systemd journal (Linux only) — last 24h, error priority and above.
|
||||
if command -v journalctl >/dev/null 2>&1; then
|
||||
echo "--- journalctl -p err --since '24 hours ago' ---"
|
||||
journalctl -p err --since '24 hours ago' --no-pager 2>/dev/null | tail -100
|
||||
echo
|
||||
fi
|
||||
|
||||
# 2. kubectl events (mo1 only).
|
||||
if command -v kubectl >/dev/null 2>&1; then
|
||||
echo "--- kubectl get events --all-namespaces (warnings) ---"
|
||||
kubectl get events --all-namespaces --field-selector type!=Normal 2>/dev/null | tail -50
|
||||
echo
|
||||
fi
|
||||
|
||||
# 3. Recent (mtime < 7d) log files: count error tokens.
|
||||
PATTERN='ERROR|FATAL|CRITICAL|FAIL(ED|URE)?|panic|segfault|OOM|Out of memory|denied'
|
||||
WPAT='WARN(ING)?'
|
||||
|
||||
scan_file() {
|
||||
f="$1"
|
||||
case "$f" in
|
||||
*.gz) cmd="zcat -- \"$f\"" ;;
|
||||
*.xz) cmd="xzcat -- \"$f\"" ;;
|
||||
*.zst) cmd="zstdcat -- \"$f\"" ;;
|
||||
*.zip) return ;;
|
||||
*) cmd="cat -- \"$f\"" ;;
|
||||
esac
|
||||
errs=$(eval "$cmd" 2>/dev/null | grep -c -E "$PATTERN")
|
||||
warns=$(eval "$cmd" 2>/dev/null | grep -c -E "$WPAT")
|
||||
if [ "${errs:-0}" -gt 0 ] || [ "${warns:-0}" -gt 50 ]; then
|
||||
sz=$(stat -c '%s' "$f" 2>/dev/null || stat -f '%z' "$f" 2>/dev/null)
|
||||
printf '%s\terrors=%s\twarns=%s\tsize=%s\n' "$f" "$errs" "$warns" "$sz"
|
||||
# Show up to 5 sample error lines.
|
||||
eval "$cmd" 2>/dev/null | grep -E "$PATTERN" | head -5 | sed 's/^/ > /'
|
||||
fi
|
||||
}
|
||||
|
||||
echo "--- recent log files (mtime < 7d) ---"
|
||||
# Use locate when possible; otherwise restrict to /var/log walk.
|
||||
{
|
||||
if command -v plocate >/dev/null 2>&1; then plocate /var/log 2>/dev/null
|
||||
elif command -v locate >/dev/null 2>&1; then locate /var/log 2>/dev/null
|
||||
fi
|
||||
[ -d /var/log ] && du -a /var/log 2>/dev/null | awk '{ $1=""; sub(/^ /,""); print }'
|
||||
} | sort -u | while IFS= read -r f; do
|
||||
[ -f "$f" ] || continue
|
||||
case "$f" in *.log|*.log.*|*/messages|*/syslog|*/auth*|*/kern*|*/daemon*) ;; *) continue ;; esac
|
||||
# mtime within 7 days
|
||||
if [ "$(find "$f" -prune -mtime -7 2>/dev/null)" = "$f" ]; then
|
||||
scan_file "$f"
|
||||
fi
|
||||
done
|
||||
|
||||
# 4. Disk usage of /var/log overall.
|
||||
echo
|
||||
echo "--- /var/log disk usage ---"
|
||||
du -sh /var/log 2>/dev/null
|
||||
du -sh /var/log/* 2>/dev/null | sort -h | tail -15
|
||||
|
||||
# 5. Largest log files
|
||||
echo
|
||||
echo "--- top 15 largest files under /var/log ---"
|
||||
du -ab /var/log 2>/dev/null | sort -nr | head -15 | awk '{ printf "%10d %s\n", $1, $2 }'
|
||||
Reference in New Issue
Block a user