WordPress-Logs auswerten: Zugriffe, Fehler und Angriffe erkennen
So führen Sie Zugriffsprotokoll des Webservers und WordPress-Fehlerprotokoll zusammen, schützen debug.log vor fremdem Zugriff, erkennen Passwort-Angriffe und PHP-Fehler mit Standardbefehlen und erzeugen einen täglichen Kurzbericht.
Werbung Mit * markierte Links sind Werbelinks: Bei einem Kauf erhalten wir eine Provision, der Preis bleibt gleich. Mehr dazu

Wenn eine WordPress-Website langsam wird, eine weiße Seite zeigt oder nachts tausende Anmeldeversuche abbekommt, steht die Antwort fast immer in einer Protokolldatei. Die Protokolle liegen aber an verschiedenen Stellen, und selten schaut jemand hinein. Diese Anleitung zeigt, wie Sie die Protokolle an einem festen Ort zusammenführen, sie mit wenigen Standardbefehlen lesen und daraus einen kurzen Bericht machen, der Zugriffe, Fehler und Angriffsmuster auf einen Blick zeigt.
Voraussetzungen
Die Befehle setzen einen Server voraus, auf dem Sie selbst Dateien lesen dürfen.
- WordPress: eine aktuelle Version.
- PHP: 7.4 oder neuer, empfohlen 8.3 oder 8.4.
- Webserver: Apache oder nginx unter Linux mit dem üblichen Protokollformat „combined“.
- Zugriff: SSH mit Leserechten auf die Logverzeichnisse, dazu Schreibzugriff auf die
wp-config.phpper SSH oder SFTP. - Rolle: Administrator der WordPress-Installation und Verantwortung für den Server.
- Backup: eine aktuelle Sicherung der
wp-config.php. Ein Tippfehler in dieser Datei legt die Website sofort lahm.
Schritt 1: Wissen, welches Protokoll was enthält
Jede Quelle beantwortet eine andere Frage:
| Protokoll | Typischer Ort | Beantwortet |
|---|---|---|
| Zugriffsprotokoll | /var/log/apache2/access.log bzw. /var/log/nginx/access.log | Wer hat wann welche Adresse aufgerufen, mit welchem Ergebnis? |
| Fehlerprotokoll Webserver | error.log im selben Ordner | Probleme des Webservers selbst |
| WordPress-Fehlerprotokoll | wp-content/debug.log oder eigener Pfad | PHP-Warnungen und schwere Fehler aus Core, Plugins und Themes |
| Aktivitätsprotokoll | Datenbank, per Plugin | Welcher Benutzer hat im Backend was geändert? |
Die Pfade gelten für Debian und Ubuntu. Anderswo verraten die Direktiven CustomLog (Apache) bzw. access_log (nginx) den Ort. Im offiziellen Docker-Image schreibt Apache auf die Standardausgabe, dort lesen Sie mit docker compose logs.
Das Aktivitätsprotokoll behandelt die Anleitung Aktivitätsprotokoll in WordPress einrichten.
Führen Sie ls -la /var/log/apache2/ (bzw. /var/log/nginx/) aus. Sie sollten access.log und error.log sehen, dazu ältere, rotierte Dateien wie access.log.1 und access.log.2.gz.
Schritt 2: WordPress-Fehler in eine sichere Datei schreiben
Mit den Standardeinstellungen protokolliert WordPress keine eigenen Fehler. Die Konstante WP_DEBUG_LOG schaltet das ein, setzt aber WP_DEBUG voraus. Mit true landet es in wp-content/debug.log. Diese Datei ist über den Browser erreichbar: Der Aufruf von /wp-content/debug.log liefert ohne weitere Maßnahmen in der Regel den Status 200 und den vollständigen Inhalt mit Dateipfaden des Servers. Laut WordPress-Dokumentation dürfen Sie statt true einen eigenen Dateipfad angeben. Nutzen Sie das und legen Sie die Datei außerhalb des Webverzeichnisses ab.
Ordner anlegen und dem PHP-Benutzer übergeben (auf Debian www-data):
$ sudo mkdir -p /var/log/wordpress
$ sudo chown www-data:www-data /var/log/wordpress
$ sudo chmod 750 /var/log/wordpressTragen Sie dann in die wp-config.php oberhalb der Zeile /* That's all, stop editing! */ ein:
define( 'WP_DEBUG', true );
define( 'WP_DEBUG_LOG', '/var/log/wordpress/debug.log' );
define( 'WP_DEBUG_DISPLAY', false );
@ini_set( 'display_errors', 0 );WP_DEBUG_DISPLAY auf false ist auf einer Live-Website Pflicht. Sonst sehen Besucher Warnungen mitten im Seiteninhalt. Dauerhaft eingeschaltet protokolliert WP_DEBUG auch harmlose Hinweise, die Datei wächst schneller. Gezieltes Debuggen zeigt die Anleitung WordPress Debug-Modus aktivieren und Error-Logs analysieren.
Können Sie auf Ihrem Hosting keinen Ordner außerhalb des Webverzeichnisses anlegen, sperren Sie die Datei wenigstens. Unter Apache genügt eine .htaccess im Ordner wp-content, sofern der Hoster AllowOverride erlaubt:
<Files "debug.log">
Require all denied
</Files>Unter nginx gehört eine entsprechende Regel in den Server-Block:
location = /wp-content/debug.log {
deny all;
}Rufen Sie eine Seite der Website auf und prüfen Sie mit sudo ls -la /var/log/wordpress/, ob die Datei nach der ersten Meldung entsteht. Mit curl -I https://ihre-domain.de/wp-content/debug.log sollten Sie keinen Status 200 mehr erhalten. Die Sperre per .htaccess liefert den Status 403.
Schritt 3: Das Zugriffsprotokoll lesen
Eine Zeile im Format „combined“ sieht so aus:
203.0.113.7 - - [30/Sep/2026:20:36:37 +0000] "POST /wp-login.php HTTP/1.1" 200 10053 "-" "curl/8.14.1"Von links nach rechts stehen dort IP-Adresse, zwei meist leere Felder, Zeitpunkt, Anfrage mit Methode und Pfad, Statuscode, Antwortgröße in Bytes, die verweisende Seite und die Kennung des Browsers. An Leerzeichen getrennt liegt die IP-Adresse im ersten Feld, die Methode im sechsten, der Pfad im siebten und der Statuscode im neunten.
Wie viele Anfragen endeten mit welchem Status? Die Befehle für IP-Adressen und Serverfehler folgen demselben Muster und stehen im Skript in Schritt 6.
$ awk '{print $9}' /var/log/apache2/access.log | sort | uniq -c | sort -rnÄltere, bereits komprimierte Dateien lesen Sie mit zcat -f, das unkomprimierte und gepackte Dateien gleichermaßen verarbeitet:
zcat -f /var/log/apache2/access.log* | grep -c "POST /wp-login.php"Steht ein Reverse Proxy oder CDN davor, sehen oft alle Besucher gleich aus. Die echte Adresse übernehmen mod_remoteip (Apache) bzw. das realip-Modul (nginx), die nur eigenen Proxys vertrauen dürfen. Das Apache-Format „vhost_combined“ verschiebt alle Felder um eine Position. Prüfen Sie deshalb eine echte Zeile, bevor Sie Feldnummern übernehmen.
Rufen Sie Ihre Startseite einmal im Browser auf und suchen Sie mit grep "IHRE-IP" /var/log/apache2/access.log | tail -3 nach Ihrer eigenen Adresse. Die letzte Zeile sollte Ihren Aufruf mit Status 200 zeigen.
Schritt 4: Angriffsmuster erkennen
Automatisierte Angriffe hinterlassen deutliche Spuren im Zugriffsprotokoll.
Fehlgeschlagene Anmeldungen: WordPress beantwortet eine falsche Anmeldung auf wp-login.php mit Status 200, weil es das Formular samt Fehlermeldung erneut ausliefert. Eine erfolgreiche Anmeldung leitet mit Status 302 ins Backend weiter. Viele POST-Anfragen mit Status 200 von derselben Adresse deuten daher auf einen Passwort-Angriff hin:
$ awk '$6 == "\"POST" && $7 ~ /^\/wp-login\.php/ && $9 == 200 {print $1}' /var/log/apache2/access.log | sort | uniq -c | sort -rn | headXML-RPC: Die Schnittstelle xmlrpc.php antwortet auch bei falschen Zugangsdaten mit Status 200, weil der Fehler im Inhalt der Antwort steht. So kommt die Meldung „Der Benutzername oder das Passwort ist falsch.“ zurück. Nutzen Sie keine XML-RPC-Dienste wie die Jetpack-App, ist jede POST-Anfrage darauf verdächtig. Der Tagesbericht zählt sie.
Suche nach vergessenen Dateien: Scanner fragen nach Pfaden wie /.env, /wp-config.php.bak, /phpmyadmin/ oder /wp-content/debug.log:
$ grep -E '\.env|\.bak|\.sql|phpmyadmin|debug\.log' /var/log/apache2/access.log | awk '{print $1, $7, $9}'Verlassen Sie sich dabei nicht allein auf den Statuscode. WordPress antwortet auf nicht vorhandene Pfade mit Weiterleitung (301) oder sogar mit 200 und der Startseite. Entspricht die Antwortgröße Ihrer Startseite, hat der Scanner nichts bekommen.
Benutzernamen ausspähen: Anfragen wie /?author=1 oder /wp-json/wp/v2/users sammeln Anmeldenamen.
Wiederkehrende Angreifer sperren Sie automatisch, wie die Anleitung fail2ban für wp-login und XML-RPC zeigt.
Melden Sie sich einmal absichtlich mit einem falschen Passwort an. Der Befehl für fehlgeschlagene Anmeldungen sollte Ihre IP-Adresse mit mindestens einem Treffer zeigen.
Schritt 5: PHP-Fehler bündeln und einordnen
Dieselbe Meldung steht oft hunderte Male im Protokoll. Ohne Zeitstempel gezählt, sehen Sie sofort den Hauptverursacher:
$ grep -E 'PHP (Fatal error|Warning|Parse error)' /var/log/wordpress/debug.log | sed -E 's/^\[[^]]+\] //' | sort | uniq -c | sort -rn | headEine typische Ausgabe sieht so aus:
1 PHP Fatal error: Uncaught Error: Call to undefined function nicht_vorhanden() in /var/www/html/wp-content/mu-plugins/logtest2.php:1
1 PHP Warning: Undefined variable $undefiniert in /var/www/html/wp-content/mu-plugins/logtest.php on line 1Der Pfad hinter „in“ verrät den Verursacher. Liegt er unter wp-content/plugins/NAME/, ist es das Plugin NAME, unter wp-content/themes/ das Theme. Ein „Fatal error“ bricht die Seite ab, im Zugriffsprotokoll steht zur selben Minute ein Status 500. So ordnen Sie die Meldung „Es gab einen kritischen Fehler auf dieser Website“ einer Ursache zu. Warnungen und „Deprecated“-Hinweise stören meist nicht, kündigen aber Probleme beim nächsten PHP-Update an.
Der Befehl sollte eine nach Häufigkeit sortierte Liste liefern. Bleibt sie trotz Fehlern leer, siehe „Typische Fehler“.
Schritt 6: Einen Tagesbericht erzeugen
Fassen Sie die Befehle in /usr/local/bin/wp-logbericht zusammen:
#!/bin/sh
# wp-logbericht: Kurzbericht aus Apache-Zugriffslog und WordPress-debug.log
ACCESS=${ACCESS:-/var/log/apache2/access.log}
DEBUG=${DEBUG:-/var/log/wordpress/debug.log}
echo "== Anfragen je Statuscode"
awk '{print $9}' "$ACCESS" | sort | uniq -c | sort -rn
echo "== Top 10 IP-Adressen"
awk '{print $1}' "$ACCESS" | sort | uniq -c | sort -rn | head -10
echo "== Fehlgeschlagene Anmeldungen (POST wp-login.php mit Status 200)"
awk '$6 == "\"POST" && $7 ~ /^\/wp-login\.php/ && $9 == 200 {print $1}' "$ACCESS" | sort | uniq -c | sort -rn | head -10
echo "== POST auf xmlrpc.php"
grep -c 'POST /xmlrpc.php' "$ACCESS"
echo "== Serverfehler (5xx)"
awk '$9 ~ /^5/ {print $4, $7}' "$ACCESS" | tail -10
echo "== Häufigste PHP-Meldungen"
grep -E 'PHP (Fatal error|Warning|Parse error)' "$DEBUG" | sed -E 's/^\[[^]]+\] //' | sort | uniq -c | sort -rn | head -10Ausführbar machen und testen, bei nginx mit anderem Pfad:
$ sudo chmod +x /usr/local/bin/wp-logbericht
$ sudo wp-logbericht
$ sudo ACCESS=/var/log/nginx/access.log wp-logberichtTäglich per Cron in /etc/cron.d/wp-logbericht:
55 23 * * * root /usr/local/bin/wp-logbericht > /var/log/wordpress/bericht-$(date +\%F).txt 2>&1Das Prozentzeichen muss in Cron maskiert sein, sonst bricht die Zeile ab. Wer diese Durchsicht zusammen mit Updates und Sicherungen nicht selbst im Kalender halten möchte, kann die laufende Pflege abgeben: Die WordPress-Wartung von wordpressupdate.de spielt Updates von WordPress, Plugins und Themes mit Kompatibilitätsprüfung ein, sichert die Website wöchentlich auf externen Speicher und richtet eine Firewall ein, die viele der hier sichtbaren Angriffe abfängt.
sudo wp-logbericht sollte alle sechs Abschnitte ausgeben. Am Tag nach dem Eintrag in Cron liegt eine Datei bericht-JJJJ-MM-TT.txt in /var/log/wordpress/.
Schritt 7: Rotation und Aufbewahrung festlegen
Die Webserver-Pakete von Debian und Ubuntu bringen bereits eine Regel für logrotate mit. In der Regel rotiert die Apache-Vorlage täglich, bewahrt 14 Dateien auf und komprimiert ältere Stände. Das eigene debug.log kennt logrotate dagegen nicht, es wächst ohne Grenze. Legen Sie dafür /etc/logrotate.d/wordpress an:
/var/log/wordpress/*.log {
weekly
rotate 4
compress
missingok
notifempty
copytruncate
}copytruncate kopiert die Datei und leert das Original, statt sie zu verschieben. So schreibt PHP ohne Neustart weiter. Alte Berichte räumt find /var/log/wordpress -name 'bericht-*.txt' -mtime +30 -delete per Cron auf.
Die Aufbewahrungsdauer ist auch eine Datenschutzfrage. Dynamische IP-Adressen können laut EuGH (Urteil C-582/14 vom 19. Oktober 2016) personenbezogene Daten sein. Speichern Sie Zugriffsprotokolle nur so lange, wie Sie sie für Sicherheit und Fehlersuche brauchen, und nennen Sie diese Dauer in der Datenschutzerklärung. Mehr dazu in der Anleitung DSGVO-Löschpflichten für Backups und Logfiles.
sudo logrotate -d /etc/logrotate.d/wordpress führt einen Probelauf ohne Änderungen aus und zeigt, welche Dateien rotiert würden.
Typische Fehler
- Die Datei
debug.logentsteht nicht WP_DEBUGsteht auffalse, oder der PHP-Benutzer darf nicht in den Zielordner schreiben. Prüfen Sie mitls -ld /var/log/wordpress, dass der Ordnerwww-datagehört.debug.logist öffentlich abrufbarDas passiert bei
WP_DEBUG_LOGauftrueohne Sperre. Eigenen Pfad außerhalb des Webverzeichnisses wählen oder die Sperre aus Schritt 2 setzen.- Alle Zugriffe kommen von derselben IP-Adresse
Ein Proxy oder CDN steht davor, und die echte Adresse wird nicht übernommen.
mod_remoteipbzw. das realip-Modul von nginx einrichten.- Protokoll im Docker-Container leer
Im offiziellen Image zeigen die Dateien auf die Standardausgabe, lesen Sie mit
docker compose logs.- Permission denied beim Lesen
Die Dateien gehören
rootund der Gruppeadm. Befehle mitsudoausführen oder den eigenen Benutzer der Gruppeadmhinzufügen.
Häufige Fragen
Brauche ich dafür ein Log-Plugin in WordPress?
Nein. Die Protokolle des Webservers entstehen ohnehin, und WordPress schreibt Fehler mit einer Konstante in der wp-config.php. Plugins lohnen sich für das Aktivitätsprotokoll im Backend.
Mein Hoster bietet keinen SSH-Zugang. Was nun?
Viele Hoster stellen die Zugriffs- und Fehlerprotokolle im Kundenmenü zum Download bereit. Die Befehle laufen dann auf Ihrem Rechner, unter Windows etwa im Windows-Subsystem für Linux.
Wann brauche ich ein zentrales Log-System wie Graylog oder OpenObserve?
Sobald Sie mehrere Websites oder Server betreuen und Protokolle über Wochen durchsuchen wollen. Für eine einzelne Website reicht der Tagesbericht.
Fazit
Mit einem geschützten Fehlerprotokoll, einer Handvoll Standardbefehlen und einem kurzen Tagesbericht wissen Sie, was auf Ihrer Website passiert, ohne zusätzliche Software zu installieren. Wichtig sind regelmäßige Durchsicht und kurze Aufbewahrung. Soll sich jemand anderes um Updates, Sicherungen und Firewall kümmern, übernimmt das die WordPress-Wartung von Marcel Schönfelder.
Weiterführende Anleitungen und Quellen
- WordPress Debug-Modus aktivieren: Error-Logs analysieren und Fehler selbst beheben
- WordPress-Firewall auf Serverebene: fail2ban für wp-login und XML-RPC
- Aktivitätsprotokoll in WordPress: Änderungen von Benutzern nachvollziehen
- DSGVO-Löschpflichten und Backups: Praxis-Leitfaden für Admins
- Linux-Server absichern mit UFW und Fail2ban
- WordPress Developer Resources: Debugging in WordPress
- Apache HTTP Server 2.4: Log Files
- nginx: Module ngx_http_log_module


