Nginx-Log-Analyse meistern für effiziente Fehlerbehebung
Entdecken Sie effiziente Fehlerbehebung durch die Beherrschung von Nginx-Zugriffs- und Fehlerprotokollen. Diese Anleitung zeigt, wie Sie benutzerdefinierte Protokollformate konfigurieren, um wichtige Zeitmesswerte zu erfassen und Leistungsengpässe in Nginx oder dem vorgelagerten Anwendungsserver zu identifizieren. Lernen Sie, kritische Probleme wie 502- und 504-Fehler mithilfe von Fehlerprotokoll-Schweregraden sofort zu diagnostizieren und leistungsstarke Shell-Befehle (`grep`, `awk`) zu nutzen, um Verkehrsmuster schnell zu filtern, zu zählen und zu analysieren.
Nginx-Log-Analyse meistern für effiziente Fehlerbehebung
Nginx-Protokolle sind in der Regel der schnellste Weg, um aus "die Seite ist down" ein konkretes Problem zu machen. Das Zugriffsprotokoll zeigt, was Clients angefordert haben und welchen Status sie erhalten haben. Das Fehlerprotokoll zeigt, was Nginx nicht tun konnte: Verbindung zu einem Upstream herstellen, ein Zertifikat lesen, eine Datei öffnen, eine Konfiguration parsen oder lange genug auf eine Backend-Antwort warten.
Gute Nginx-Log-Analyse bedeutet nicht, Dateien anzustarren, bis etwas verdächtig aussieht. Es geht darum, eine enge Frage zu stellen, schnell zu filtern und das Zugriffsprotokoll mit dem Fehlerprotokoll und den vorgelagerten Anwendungsprotokollen zu korrelieren. Ein 502 im Zugriffsprotokoll ist ein Symptom. Die passende Fehlerprotokollzeile ist in der Regel der Anfang der Antwort.
1. Nginx-Log-Grundlagen: Zugriff vs. Fehler
Nginx führt zwei verschiedene Arten von Protokollen, die jeweils eine kritische, separate Funktion erfüllen:
1.1 Das Zugriffsprotokoll (access.log)
Das Zugriffsprotokoll zeichnet Details zu jeder Anfrage auf, die Nginx verarbeitet. Es ist entscheidend für das Verständnis des Benutzerverhaltens, die Überwachung des Datenverkehrsflusses und die Bewertung von Antwortzeiten.
Standardpfad: Typischerweise /var/log/nginx/access.log
Zweck: Verfolgung von Client-Interaktionen, erfolgreichen Anfragen, Client-Fehlern, Server-Fehlern, die über Nginx zurückgegeben werden, gesendeten Bytes, User-Agents und Anfragezeitmessung, falls konfiguriert.
1.2 Das Fehlerprotokoll (error.log)
Das Fehlerprotokoll verfolgt interne Probleme, Betriebsfehler und Kommunikationsprobleme, die während des Nginx-Verarbeitungslebenszyklus auftreten. Dieses Protokoll ist die definitive Quelle für die Fehlerbehebung bei Backend-Konnektivitätsproblemen und Serverkonfigurationsfehlern.
Standardpfad: Typischerweise /var/log/nginx/error.log
Zweck: Verfolgung von serverseitigen Fehlern, Warnungen und Systemereignissen (5xx-Fehler, Fehler beim Parsen von Konfigurationsdateien).
Schweregrade des Fehlerprotokolls
Nginx verwendet acht Schweregrade. Bei der Fehlerbehebung sollten Sie in der Regel auf der Stufe error oder höher beginnen. Der Schweregrad wird mit der Direktive error_log konfiguriert:
# Setze minimalen Schweregrad auf 'warn'
error_log /var/log/nginx/error.log warn;
| Stufe | Beschreibung | Priorität |
|---|---|---|
| crit | Kritische Bedingungen, wie ein schwerwiegender Laufzeitfehler | Höchste |
| error | Ein Fehler ist aufgetreten, der die Bearbeitung einer Anfrage verhindert hat | Hoch |
| warn | Etwas Unerwartetes ist passiert, aber der Betrieb läuft weiter | Mittel |
| notice | Normaler, aber bedeutender Zustand (z.B. Server-Neustart) | Niedrig |
| info | Informationsmeldungen | Niedrigste |
Es gibt auch die Stufen emerg, alert und debug. debug kann extrem laut sein und erfordert in der Regel einen Nginx-Build mit Debug-Unterstützung. Verwenden Sie es für gezielte Fehlerbehebung, nicht als normale Produktionseinstellung.
2. Anpassen von Zugriffsprotokollen für die Leistungsanalyse
Das standardmäßige Nginx-Zugriffsprotokollformat, oft combined genannt, ist nützlich, enthält aber keine entscheidenden Leistungszeitvariablen. Um Langsamkeit effektiv zu beheben, müssen Sie ein benutzerdefiniertes Format definieren, das erfasst, wie lange Nginx für die Verarbeitung der Anfrage und wie lange der Upstream-Server gebraucht hat.
2.1 Definieren eines Leistungsprotokollformats
Verwenden Sie die Direktive log_format (normalerweise in nginx.conf definiert), um ein benutzerdefiniertes Format zu erstellen, z.B. timing_log:
log_format timing_log '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'$request_time $upstream_response_time';
server {
listen 80;
server_name example.com;
# Wende das benutzerdefinierte Format hier an
access_log /var/log/nginx/timing_access.log timing_log;
# ... restliche Konfiguration
}
| Variable | Beschreibung | Wert für die Fehlerbehebung |
|---|---|---|
| $request_time | Gesamtzeit vom ersten empfangenen Byte bis zum letzten gesendeten Byte. | Hohe Werte deuten auf langsames Netzwerk, langsames Nginx oder langsames Backend hin. |
| $upstream_response_time | Zeit, die auf die Antwort des Upstream-Servers (z.B. Anwendungsserver) gewartet wurde. | Hohe Werte hier identifizieren die Backend-Anwendung als Engpass. |
| $status | HTTP-Statuscode, der an den Client zurückgegeben wurde. | Wesentlich zum Filtern von Fehlern (4xx, 5xx). |
Erwägen Sie die Verwendung von JSON-Protokollformatierung, wenn Protokolle an ein zentrales System gesendet werden. JSON ist mit dem Auge schwerer zu lesen, aber für Tools viel einfacher zuverlässig zu parsen. Wenn Sie Klartextprotokolle behalten, beachten Sie, dass awk-Feldnummern brechen können, wenn User-Agents, Anforderungspfade oder in Anführungszeichen gesetzte Felder Leerzeichen enthalten.
Erwägen Sie auch die Protokollierung von Anforderungs-IDs. Wenn Ihr Load Balancer oder Ihre Anwendung bereits einen Anforderungs-ID-Header sendet, leiten Sie ihn durch und protokollieren Sie ihn:
log_format timing_log '$remote_addr [$time_local] '
'"$request" $status $body_bytes_sent '
'request_time=$request_time '
'upstream_time=$upstream_response_time '
'request_id=$request_id '
'upstream=$upstream_addr';
Eine Anforderungs-ID ermöglicht es Ihnen, eine langsame öffentliche Anfrage mit einem Anwendungsprotokolleintrag zu verbinden. Ohne sie müssen Sie nach Zeitstempel, Pfad und Client-IP abgleichen, was möglich, aber viel weniger angenehm ist.
3. Interpretieren von Zugriffsprotokolleinträgen
Ein typischer Eintrag mit dem benutzerdefinierten Format könnte so aussehen (mit am Ende hinzugefügten Zeitwerten):
192.168.1.10 - - [10/May/2024:14:30:05 +0000] "GET /api/data HTTP/1.1" 200 450 "-" "Mozilla/5.0" 0.534 0.528
Diagnose:
- Statuscode (200): Erfolg.
- Anfragezeit (0.534s): Gesamtzeit beträgt eine halbe Sekunde.
- Upstream-Zeit (0.528s): Fast die gesamte Zeit wurde auf die Backend-Anwendung gewartet (
0.534 - 0.528 = 0.006svon Nginx-Overhead verbraucht).
Diagnose: Für diese Anfrage ist die Backend-Anwendung die wahrscheinliche Quelle der 500ms-Latenz. Der Nginx-Overhead erscheint gering.
Verallgemeinern Sie nicht von einer einzelnen Zeile. Betrachten Sie eine Stichprobe langsamer Anfragen. Wenn die meisten langsamen Anfragen eine hohe $upstream_response_time haben, konzentrieren Sie sich auf die App oder das Upstream-Netzwerk. Wenn $request_time hoch ist, während $upstream_response_time niedrig ist, kann die Verzögerung auf die Client-Upload-Zeit, langsamen Client-Download, Pufferungsverhalten oder Nginx-seitige Arbeit zurückzuführen sein.
Fehlerbehebung mit Statuscodes
| Statuscode-Bereich | Bedeutung | Typische Aktion/Protokollquelle |
|---|---|---|
| 4xx (Client-Fehler) | Client hat eine ungültige oder nicht autorisierte Anfrage gesendet. | Zugriffsprotokolle auf hohe Häufigkeit prüfen. Suchen Sie nach 404 Not Found (fehlende Dateien) oder 403 Forbidden (Berechtigungsprobleme). |
| 5xx (Server-Fehler) | Nginx oder ein Upstream-Server konnte eine gültige Anfrage nicht erfüllen. | Sofort das Fehlerprotokoll auf entsprechende Einträge prüfen. |
| 502 Bad Gateway | Nginx konnte keine Antwort vom Upstream-Anwendungsserver erhalten. | Fehlerprotokoll zeigt Details (Verbindung abgelehnt, Zeitüberschreitung). |
| 504 Gateway Timeout | Der Upstream-Server hat zu lange gebraucht, um innerhalb der konfigurierten Proxy-Grenzen zu antworten. | Fehlerprotokoll zeigt Timeout-Warnungen. Untersuchen Sie die Backend-Latenz, bevor Sie Timeouts erhöhen. |
Das Erhöhen von proxy_read_timeout kann das Symptom verbergen, während Benutzer immer noch zu lange warten. Es ist gültig für langlebige Endpunkte, Streaming oder bekannte langsame Operationen, aber für normale API-Anfragen sollte es zuerst eine Backend-Untersuchung auslösen.
4. Diagnose kritischer Probleme im Fehlerprotokoll
Wenn eine Anfrage zu einem 5xx-Fehler führt, sagt Ihnen das Zugriffsprotokoll nur, dass der Fehler aufgetreten ist. Das Fehlerprotokoll sagt Ihnen, warum.
Fallstudie: 502 Bad Gateway
Ein 502-Fehler ist eines der häufigsten Probleme bei der Verwendung von Nginx als Reverse Proxy. Er weist fast immer darauf hin, dass die Backend-Anwendung ausgefallen, überlastet oder nicht erreichbar ist.
Suchen Sie im Fehlerprotokoll nach diesen spezifischen Meldungen:
4.1 Verbindung abgelehnt (Backend ausgefallen)
Dies zeigt an, dass Nginx versucht hat, eine Verbindung zum Backend-Port herzustellen, aber nichts hat zugehört, was bedeutet, dass der Anwendungsserver (z.B. PHP-FPM, Gunicorn) gestoppt oder falsch konfiguriert ist.
2024/05/10 14:35:10 [error] 12345#0: *1 connect() failed (111: Connection refused) while connecting to upstream, client: 192.168.1.10, server: example.com, request: "GET /test"
- Aktion: Überprüfen Sie, ob der Backend-Dienst läuft, ob er auf dem erwarteten Port oder Unix-Socket lauscht und ob Nginx auf dieselbe Adresse zeigt. Starten Sie erst neu, nachdem Sie verstanden haben, warum er gestoppt wurde.
4.2 Upstream hat Verbindung vorzeitig geschlossen (Backend-Absturz)
Dies passiert, wenn Nginx eine Verbindung herstellt, der Backend-Server sie jedoch beendet, bevor eine vollständige HTTP-Antwort gesendet wird. Dies deutet oft auf einen schwerwiegenden Fehler oder Absturz im Anwendungscode hin.
2024/05/10 14:38:22 [error] 12345#0: *2 upstream prematurely closed connection while reading response header from upstream, client: 192.168.1.10, server: example.com, request: "POST /submit"
- Aktion: Überprüfen Sie die nativen Fehlerprotokolle des Anwendungsservers (z.B. PHP-FPM-Protokolle, Node.js-Protokolle) auf den spezifischen schwerwiegenden Fehler.
Warnung: Wenn Nginx beim Start seine Konfigurationsdatei nicht lesen kann, wird der Fehler oft direkt auf die Standardfehlerausgabe oder eine Bootstrap-Protokolldatei ausgegeben, nicht in das konfigurierte
error.log. Überprüfen Sie immerjournalctl -xeoder Systemprotokolle, wenn Nginx nicht startet.
Fallstudie: 403 Forbidden
Ein 403 im Zugriffsprotokoll kann durch Anwendungsautorisierung, Nginx-Zugriffsregeln, Dateisystemberechtigungen oder Verzeichnisindexverhalten verursacht werden. Das Zugriffsprotokoll allein kann Ihnen nicht sagen, welches.
Suchen Sie im Fehlerprotokoll nach Zeilen wie:
2024/05/10 15:02:01 [error] 12345#0: *12 directory index of "/var/www/site/" is forbidden
Das bedeutet, dass Nginx ein Verzeichnis erreicht hat, aber keine Indexdatei zum Ausliefern hatte und die Verzeichnisauflistung deaktiviert ist. Die Lösung kann darin bestehen, die erwartete index.html zu erstellen, die index-Direktive anzupassen oder die Anfrage an die Anwendung weiterzuleiten.
Bei Berechtigungsproblemen sehen Sie möglicherweise:
2024/05/10 15:04:44 [error] 12345#0: *15 open() "/var/www/site/private.txt" failed (13: Permission denied)
Überprüfen Sie Dateibesitzer, Verzeichnisausführungsberechtigungen, SELinux- oder AppArmor-Richtlinien, falls zutreffend, und den Benutzer, unter dem Nginx-Worker laufen.
Fallstudie: 499 Client Closed Request
Der Nginx-spezifische Status 499 bedeutet, dass der Client die Verbindung geschlossen hat, bevor Nginx die Antwort beendet hat. Dies ist üblich, wenn Benutzer navigieren, mobile Clients die Verbindung verlieren oder ein Upstream so lange braucht, dass der Client aufgibt.
Behandeln Sie nicht jeden 499 als Nginx-Fehler. Betrachten Sie das Timing. Wenn viele 499s eine hohe Anforderungszeit haben und mit langsamen Upstreams übereinstimmen, geben Benutzer möglicherweise langsame Anfragen auf. Wenn sie sofort von einem Client oder Netzwerk auftreten, kann es sich um Client-Verhalten handeln.
5. Praktische Shell-Befehle für die Log-Analyse
Während robuste Log-Überwachungssysteme für die Produktion empfohlen werden, bietet die Linux-Kommandozeile leistungsstarke Werkzeuge für schnelle, Echtzeit-Fehlerbehebung.
5.1 Echtzeit-Überwachung
Überwachen Sie Protokolle, während Anfragen eingehen (besonders nützlich nach dem Bereitstellen eines Fixes oder Testen einer neuen Funktion):
tail -f /var/log/nginx/access.log
# Oder nur für Fehler
tail -f /var/log/nginx/error.log
Für rotierte und komprimierte Protokolle verwenden Sie zgrep:
zgrep '" 50[0-9] ' /var/log/nginx/access.log*.gz
Log-Rotation ist bei der Überprüfung von Vorfällen wichtig. Der Fehler könnte kurz vor Mitternacht oder vor einem Rotationsjob aufgetreten sein, der die gestrige Datei komprimiert hat.
5.2 Filtern und Zählen von Fehlern
Finden und zählen Sie schnell die häufigsten 5xx-Fehler der letzten Stunde oder des letzten Tages:
# Alle 5xx-Anfragen finden
grep '" 50[0-9] ' /var/log/nginx/access.log | less
# Verteilung der 5xx-Fehler zählen (z.B. wie viele 502s vs. 504s)
grep '" 50[0-9] ' /var/log/nginx/access.log | awk '{print $9}' | sort | uniq -c | sort -nr
Erklärung: awk '{print $9}' isoliert den HTTP-Statuscode (unter der Annahme des Standard- oder Combined-Log-Formats, bei dem der Status das 9. Feld ist).
Wenn Sie ein benutzerdefiniertes Log-Format verwenden, bestätigen Sie die Feldnummer, bevor Sie der Zählung vertrauen. Eine sicherere schnelle Überprüfung besteht darin, ein paar geparste Zeilen auszugeben:
awk '{print NR, $0; if (NR == 3) exit}' /var/log/nginx/access.log
Verwenden Sie für JSON-Protokolle jq anstelle von Feldnummern:
jq -r 'select(.status >= 500) | .status' /var/log/nginx/access.json \
| sort | uniq -c | sort -nr
5.3 Identifizieren langsamer Anfragen (erfordert benutzerdefiniertes Log-Format)
Wenn Sie das timing_log-Format implementiert haben (bei dem $request_time das vorletzte Feld oder in unserem Beispiel Feld 16 ist):
# Die 10 langsamsten Anfragen finden (z.B. Anfragen, die länger als 1 Sekunde dauern)
awk '($16 > 1.0) {print $16, $7}' /var/log/nginx/timing_access.log | sort -nr | head -10
Erklärung: Dieser Befehl gibt die Anforderungszeit und den URI ($7) für jede Anfrage aus, die länger als 1,0 Sekunden gedauert hat, absteigend sortiert.
Ein besser lesbares Klartext-Zeitformat verwendet benannte Werte, wie request_time=0.534. Dann können Sie weniger elegant, aber mit weniger Feldnummern-Überraschungen nach langsamen Bereichen greppen. Für ernsthafte Analysen senden Sie strukturierte Protokolle an ein Log-System und fragen Sie Perzentile nach Route ab.
5.4 Identifizieren der häufigsten anfragenden IP-Adressen
Nützlich zum Erkennen potenzieller DoS-Versuche, Verkehrsspitzen oder verdächtiger Aktivitäten:
# Die Top 20 IPs finden, die Anfragen stellen
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -nr | head -20
Top-IPs sind ein Ausgangspunkt, kein Beweis für Missbrauch. Ein Corporate NAT, CDN-Edge oder Load Balancer kann viele Benutzer als eine Quelle erscheinen lassen. Wenn Nginx hinter einem Proxy steht, konfigurieren und protokollieren Sie die echte Client-IP sorgfältig mit real_ip_header und vertrauenswürdigen Proxy-Bereichen. Vertrauen Sie niemals willkürlichen X-Forwarded-For-Headern aus dem offenen Internet.
Ein praktischer Ablauf zur Fehlerbehebung
Beginnen Sie mit dem Symptom des Benutzers und einem Zeitfenster. "Der Checkout hat um 14:35 UTC 502s zurückgegeben" ist viel nützlicher als "Nginx ist kaputt".
Zählen Sie zuerst die Statuscodes:
grep '10/May/2024:14:3' /var/log/nginx/access.log \
| awk '{print $9}' | sort | uniq -c | sort -nr
Die Datumsfilterung mit Klartextprotokollen ist umständlich, und der genaue Befehl hängt von Ihrem Log-Format ab. Für eine schnelle Überprüfung eines Vorfalls kann selbst eine grobe Filterung zeigen, ob das Problem hauptsächlich 502, 504, 403 oder 404 war.
Als nächstes ziehen Sie ein paar passende Anfragen:
grep '" 502 ' /var/log/nginx/access.log | tail -20
Notieren Sie den Zeitstempel, URI, Upstream-Zeit und Anforderungs-ID, falls vorhanden. Suchen Sie dann im Fehlerprotokoll um denselben Zeitstempel herum:
grep '14:35' /var/log/nginx/error.log
Wenn der Fehler connect() failed (111: Connection refused) lautet, überprüfen Sie den Upstream-Dienst und seinen Port. Wenn er upstream timed out lautet, überprüfen Sie die Backend-Latenz und Warteschlangen. Wenn er no live upstreams lautet, überprüfen Sie die Upstream-Health, DNS oder Load-Balancer-Konfiguration.
Überprüfen Sie schließlich die Backend-Protokolle mit derselben Anforderungs-ID oder demselben Zeitstempel. Nginx sagt Ihnen oft, wo die Übergabe fehlgeschlagen ist, aber das Backend-Protokoll sagt Ihnen, warum sich die Anwendung so verhalten hat.
Machen Sie Protokolle vor dem Ausfall nützlich
Die schlechteste Zeit, um die Protokollierung zu verbessern, ist während eines Ausfalls. Fügen Sie Anforderungszeit, Upstream-Zeit, Upstream-Adresse und Anforderungs-IDs hinzu, bevor Sie sie benötigen. Halten Sie Zugriffs- und Fehlerprotokolle nach Site getrennt, wenn ein Server mehrere Anwendungen hostet. Stellen Sie sicher, dass die Rotation genügend Verlauf für die Vorfälle behält, die Sie tatsächlich untersuchen.
Wenn etwas kaputt geht, lesen Sie die Protokolle paarweise: Zugriffsprotokoll für das, was passiert ist, Fehlerprotokoll für das, was Nginx nicht tun konnte, Anwendungsprotokoll für das, was der Upstream als nächstes getan hat. Diese Gewohnheit hält die Fehlerbehebung fokussiert und bringt Sie in der Regel schneller zum eigentlichen Fehler, als Timeouts zu ändern oder Dienste wahllos neu zu starten.