Logs und Journal
Ein Dienst startet nicht. Die Fehlermeldung von systemctl start lautet nur: «See journalctl -xeu nginx.service for details». Wer jetzt weiss, wo er nachschaut, hat das Problem meist in zwei Minuten gefunden. Logs lesen ist die halbe Administration.
Das Journal
Abschnitt betitelt „Das Journal“systemd sammelt alle Meldungen von Kernel, Diensten und Login-Vorgängen in einer Datenbank, dem Journal. Jeder Eintrag trägt Zeitstempel, Unit, Prozess und Priorität. Das Werkzeug dazu ist journalctl:
| Befehl | Zeigt |
|---|---|
journalctl |
Alles, vom ältesten Eintrag an (mit q verlassen) |
journalctl -r |
Alles, neueste zuerst |
journalctl -n 50 |
Die letzten 50 Zeilen |
journalctl -f |
Laufend neue Einträge, wie tail -f |
journalctl -u nginx |
Nur die Unit nginx |
journalctl -b |
Nur seit dem letzten Boot (-b -1 der Boot davor) |
journalctl -p err |
Nur Priorität err und schlimmer (emerg alert crit err warning notice info debug) |
journalctl --since "1 hour ago" |
Zeitfenster, auch --since today, --since "2025-11-04 08:00", --until ... |
journalctl -k |
Nur Kernel-Meldungen |
journalctl -xeu nginx |
Unit nginx, ans Ende springen, mit Erklärungen (-x) |
Die Optionen lassen sich kombinieren. Der Standardbenutzer auf Ubuntu ist in der Gruppe adm und sieht alles; sonst braucht es sudo.
Hands-on:
journalctl -n 20journalctl -b -p errjournalctl -u ssh --since todayjournalctl -u ticker -r | headjournalctl --disk-usageDu kennst systemctl status bereits: Die Zeilen unter dem Statusblock sind die letzten zehn Journal-Einträge der Unit. Für eine schnelle Diagnose reicht das oft, für alles Weitere nimmst du journalctl -u.
Eigene Meldungen ins Journal schreibst du mit logger. Damit testest du, ob ein Filter stimmt, oder schreibst aus Skripten ins Log:
logger -t lernlabor "Hallo Journal"logger -t lernlabor -p user.err "Das ist ein Fehler"journalctl -t lernlaborjournalctl -t lernlabor -p err-t setzt das Tag (den Programmnamen), -p die Priorität. In einer zweiten SSH-Sitzung kannst du journalctl -f laufen lassen und zusehen, wie die Meldungen eintreffen.
Klassische Logs in /var/log
Abschnitt betitelt „Klassische Logs in /var/log“Vor dem Journal gab es nur Textdateien, und die gibt es weiterhin. Auf Ubuntu Server läuft zusätzlich rsyslog, das die Meldungen aus dem Journal in die gewohnten Dateien schreibt. Dazu schreiben manche Programme ihre Logs selbst, ohne Umweg über systemd.
ls -lt /var/log | head -n 15sudo tail -n 5 /var/log/syslogsudo tail -n 5 /var/log/auth.logtail -n 5 /var/log/dpkg.logsudo tail -n 5 /var/log/nginx/access.log| Datei | Inhalt |
|---|---|
syslog |
Das Sammelbecken: alles, was keinen eigenen Platz hat |
auth.log |
Logins, sudo, SSH-Verbindungen, fehlgeschlagene Passwörter |
kern.log |
Kernel-Meldungen |
dpkg.log, apt/history.log |
Welche Pakete wann installiert oder entfernt wurden |
nginx/access.log, nginx/error.log |
Jede Anfrage an den Webserver beziehungsweise seine Fehler, von nginx selbst geschrieben |
wtmp, btmp |
Binär: Logins und fehlgeschlagene Logins, lesbar mit last und sudo lastb |
Mach einen Request und schau zu: curl localhost/gibtsnicht, dann sudo tail -n 2 /var/log/nginx/access.log. Du siehst die Zeile mit Status 404.
Noch drei Werkzeuge für spezielle Fragen:
sudo dmesg -T | tail -n 20last -n 10last rebootlastlog | headdmesg zeigt den Kernel-Ringpuffer (USB-Geräte, Disk-Fehler, Out-of-Memory). last listet Logins und Reboots, lastlog den letzten Login jedes Benutzers.
Logrotation
Abschnitt betitelt „Logrotation“Logdateien wachsen. Damit die Disk nicht vollläuft, dreht logrotate sie regelmässig: syslog wird zu syslog.1, dann syslog.2.gz und so weiter, alte werden gelöscht. Die Regeln liegen in /etc/logrotate.conf und pro Programm in /etc/logrotate.d/:
cat /etc/logrotate.d/nginxsystemctl list-timers logrotate.timerDas Journal begrenzt sich selbst (SystemMaxUse= in /etc/systemd/journald.conf), journalctl --vacuum-time=30d räumt von Hand auf.
Systematische Fehlersuche
Abschnitt betitelt „Systematische Fehlersuche“Ein Dienst startet nicht. Das Vorgehen ist immer dasselbe:
flowchart TD
A["sudo systemctl start NAME schlägt fehl"] --> B["systemctl status NAME<br/>Exit-Code? letzte Zeilen?"]
B --> C["journalctl -xeu NAME<br/>die eigentliche Fehlermeldung des Programms"]
C --> D{"Was sagt die Meldung?"}
D -->|"syntax error, unknown directive"| E["Konfiguration prüfen<br/>nginx -t, sshd -t, Skript von Hand starten"]
D -->|"Address already in use"| F["Port belegt?<br/>sudo ss -tlnp"]
D -->|"No such file, Permission denied"| G["Pfade und Rechte prüfen<br/>ls -l, User= in der Unit"]
E --> H["beheben, daemon-reload falls Unit geändert, start, status"]
F --> H
G --> H
Hands-on: einen belegten Port provozieren. nginx hält Port 80, ein zweiter Webserver will ihn auch:
sudo ss -tlnpsudo python3 -m http.server 80ss -tlnp listet alle TCP-Ports (t), auf denen gelauscht wird (l), numerisch (n) mit Prozess (p). Python meldet «Address already in use», und in der ss-Ausgabe steht, dass es nginx ist. Genau diese Meldung siehst du im Journal, wenn zwei Dienste denselben Port wollen.
Lösung anzeigen
script labs/linux/09-dienste/logs.txtsudo sed -i 's/sleep 10/slep 10/' /usr/local/bin/ticker.shsudo systemctl restart tickersleep 30systemctl status tickerjournalctl -xeu ticker | tail -n 30# Antwort 1: Exit-Code 127, "command not found": die Shell hat slep nicht gefunden.# Antwort 2: Fünf Mal innert 10 Sekunden (Standard: StartLimitBurst=5, StartLimitIntervalSec=10s), dann "Start request repeated too quickly" und failed.# Antwort 3: ticker.sh: line 9: slep: command not foundsudo sed -i 's/slep 10/sleep 10/' /usr/local/bin/ticker.shsudo systemctl reset-failed tickersudo systemctl start tickersystemctl status tickerexitSelbstcheck · 5 Fragen
Weiterführend
Abschnitt betitelt „Weiterführend“man journalctl,man logrotate- ubuntuusers-Wiki: journalctl