linux-cli-shell automation logging reporting bash awk nginx

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:

  1. Filter: Nur relevante Zeilen extrahieren (grep).
  2. Extrakt: Bestimmte Spalten wählen (awk/cut).
  3. Sort: Identische Einträge zusammenfassen.
  4. Count: Häufigkeiten zählen (uniq).
  5. 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, $9 etc.) 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