Lab: Log Analysis & Reporting (Artikel 298)
Automatisierte Auswertung von System- und Applikations-Logs. Erfahren Sie, wie Sie mittels Shell-Werkzeugen aussagekräftige Reports über Traffic, Fehler und Performance generieren.
# Reporting Lab: Aus Logs Wissen generieren
TL;DR / Management Summary Ein 10GB Logfile ist für einen Menschen wertlos. Ein Senior Admin nutzt die Shell, um diese Datenflut zu aggregieren. In diesem Lab bauen wir ein Reporting-Skript, das Nginx-Logs analysiert und eine übersichtliche Zusammenfassung liefert: Die Top 10 Besucher-IPs, die häufigsten Fehlermeldungen und die aufgetretenen HTTP-Statuscodes. Das Ziel: Ein täglicher E-Mail-Report, der Anomalien sofort sichtbar macht.
# 1. Das Konzept: Der Aggregations-Workflow
Vom Text zur Tabelle.
Wir nutzen die Unix-Pipeline-Philosophie:
- Filter: Nur relevante Zeilen extrahieren (grep).
- Extrakt: Bestimmte Spalten wählen (awk/cut).
- Sort: Identische Einträge zusammenfassen.
- Count: Häufigkeiten zählen (uniq).
- Report: Formatierung als Text oder HTML.
# 2. Das Skript: log_reporter.sh
Datenanalyse auf Knopfdruck.
#!/bin/bash
# ---------------------------------------------------------------------------
# LOG REPORTING TOOL
# ---------------------------------------------------------------------------
readonly LOG_FILE="/var/log/nginx/access.log"
readonly REPORT_FILE="/tmp/daily_report.txt"
readonly DATE_STR=$(date +'%d/%b/%Y' --date="yesterday")
{
echo "========================================"
echo " LOG REPORT FOR: $DATE_STR"
echo " Server: $(hostname)"
echo "========================================"
echo ""
echo "--- TOP 10 VISITOR IPS ---"
grep "$DATE_STR" "$LOG_FILE" | awk '{print $1}' | sort | uniq -c | sort -rn | head -n 10
echo ""
echo "--- HTTP STATUS CODES ---"
grep "$DATE_STR" "$LOG_FILE" | awk '{print $9}' | sort | uniq -c | sort -rn
echo ""
echo "--- TOP 10 404 NOT FOUND PATHS ---"
grep "$DATE_STR" "$LOG_FILE" | awk '$9 == "404" {print $7}' | sort | uniq -c | sort -rn | head -n 10
echo ""
echo "--- REQUESTS BY HOUR ---"
grep "$DATE_STR" "$LOG_FILE" | cut -d: -f2 | sort | uniq -c
} > "$REPORT_FILE"
# Report per Mail versenden
# mail -s "Daily Log Report" admin@company.com < "$REPORT_FILE"
cat "$REPORT_FILE"
# 3. Day-2 Operations: Fortgeschrittene Metriken
Performance-Analyse.
Wenn Ihr Log das Feld für die Antwortzeit enthält (in Nginx request_time), können Sie langsame Requests finden:
# Die 5 langsamsten URLs finden
# Angenommen, Spalte 15 ist die Antwortzeit in Sekunden
awk '$15 > 1.0 { print $15, $7 }' access.log | sort -rn | head -n 5
# 4. Troubleshooting & “War Stories”
Wenn die Datenmenge das Skript killt.
# Story 1: “Der SSD-Burnout durch Logs”
Symptom: Der Server hat massiv Last, obwohl wenig User da sind. iotop zeigt, dass das Reporting-Skript hunderte MB/s liest.
Ursache: Das Skript liest bei jedem Lauf das gesamte access.log. Bei 50GB Log-Größe dauert das Scannen Minuten.
Lösung: Nutzen Sie Log-Rotation (Artikel 340). Analysieren Sie nur die rotierte Datei des Vortages (access.log.1). Diese ist kleiner und ändert sich während des Laufs nicht.
# Story 2: “Das Regex-Falsch-Positiv”
Symptom: Der Report zeigt astronomische Zahlen bei den Fehlern, die gar nicht stimmen können.
Ursache: Die Suche nach 404 hat auch Zeilen gefunden, in denen die IP-Adresse die Zahl 404 enthielt.
Lösung: Seien Sie präziser mit awk. Anstatt grep "404" nutzen Sie awk '$9 == "404"'. Dies prüft exakt die Spalte für den HTTP-Status.
# 5. Fazit & Empfehlung
- Regelmäßigkeit: Lassen Sie den Report automatisiert nach der nächtlichen Log-Rotation laufen.
- Visualisierung: Wenn Sie grafische Dashboards brauchen, migrieren Sie zu Grafana Loki (Artikel 044/045). Für den schnellen Check per E-Mail bleibt Bash ungeschlagen.
- Wartung: Passen Sie das Spalten-Layout (
$1,$9etc.) an, wenn Sie das Log-Format Ihres Webservers ändern.
# Anhang: Cheatsheet für Log-Filter
| Ziel | Befehl |
|---|---|
| Exakte IP finden | awk '$1 == "1.2.3.4"' |
| POST Anfragen | awk '$6 == "\"POST"' |
| Suche nach User-Agent | awk -F'"' '{print $6}' |
| Traffic pro IP (MB) | awk '{sum[$1]+=$10} END {for (i in sum) print i, sum[i]/1024/1024 " MB"}' |
| PHP Fehler finden | grep "PHP Fatal error" error.log |
| Zeitfenster filtern | sed -n '/10:00:00/,/11:00:00/p' access.log |