systemd-Logs gezielt durchsuchen und korrelieren
Wer bei einem Vorfall wahllos durch Logdateien scrollt, verliert wertvolle Zeit. journalctl bündelt alle systemd-Logs an einer Stelle und bietet präzise Filter nach Dienst, Zeitraum und Schweregrad. Dieser Artikel zeigt, wie ihr Filter kombiniert, das Journal persistent konfiguriert, Dienste im Störfall korreliert und Logs sauber für Kollegen exportiert.
Inhaltsverzeichnis
- 1. Warum journalctl das zentrale Log-Werkzeug unter systemd ist
- 2. Nach Unit filtern: -u und die Zuordnung von Diensten
- 3. Zeitfenster eingrenzen: --since und --until
- 4. Nach Priorität filtern: -p und Schweregrade verstehen
- 5. Live mitlesen: -f und das Verhalten von tail -f
- 6. Persistentes versus flüchtiges Journal konfigurieren
- 7. Logs mehrerer Dienste im Vorfall korrelieren
- 8. Logs exportieren und mit Kollegen teilen
- 9. journalctl im direkten Vergleich zu klassischen Logdateien
- 10. Zusammenfassung
- 11. FAQ
1. Warum journalctl das zentrale Log-Werkzeug unter systemd ist
Auf jedem modernen Linux-System mit systemd laufen die Log-Ausgaben von Diensten, Kernel und Boot-Prozess standardmäßig im binären systemd-Journal zusammen, verwaltet vom Dienst systemd-journald. Statt zwanzig verschiedene Logdateien unter /var/log/ mit unterschiedlichen Formaten zu durchsuchen, gibt es mit journalctl ein einziges Werkzeug, das strukturierte, indizierte Einträge liefert. Jeder Eintrag trägt Metadaten wie PID, UID, Unit-Name und Boot-ID mit, die in klassischen Textlogs schlicht fehlen.
Der praktische Vorteil zeigt sich vor allem bei der Fehlersuche unter Zeitdruck: Statt grep über mehrere Dateien mit unterschiedlichen Zeitstempelformaten laufen zu lassen, filtert journalctl direkt nach Dienst, Zeitraum, Priorität oder Boot-Vorgang und liefert konsistent formatierte Ausgaben. Da das Journal binär gespeichert wird, sind Volltextsuche und Feldfilter deutlich schneller als bei reinem grep über große Textdateien, besonders wenn mehrere Gigabyte an Logs vorliegen.
2. Nach Unit filtern: -u und die Zuordnung von Diensten
Der Parameter -u beziehungsweise --unit ist der am häufigsten genutzte Filter, weil die meisten Vorfälle einem konkreten Dienst zugeordnet werden können. journalctl -u nginx.service zeigt ausschließlich Einträge, die diesem Unit zugeordnet sind, egal ob sie über stdout, stderr oder direkt über die sd_journal-API geschrieben wurden. Die Endung .service kann meist weggelassen werden, journalctl -u nginx funktioniert ebenso, sofern der Name eindeutig ist.
Mehrere Units lassen sich kombinieren, indem -u mehrfach angegeben wird, etwa journalctl -u nginx -u php8.3-fpm, was intern als logisches ODER ausgewertet wird. Für Container- oder Slice-Setups funktioniert zusätzlich --user-unit für Dienste im User-Kontext von systemd --user. Wer den genauen Unit-Namen nicht kennt, findet ihn mit systemctl list-units --type=service oder direkt über systemctl status <prozessname>, was zusätzlich die letzten Journal-Zeilen des Dienstes anzeigt.
# Show all log entries for a single unit
journalctl -u nginx.service
# Combine multiple units (logical OR)
journalctl -u nginx.service -u php8.3-fpm.service
# Filter by unit and priority together
journalctl -u mysql.service -p err
# Show only entries from the current boot for a unit
journalctl -u docker.service -b
# Find the exact unit name first
systemctl list-units --type=service | grep -i redis
3. Zeitfenster eingrenzen: --since und --until
Die Optionen --since und --until grenzen die Ausgabe auf einen konkreten Zeitraum ein und akzeptieren sowohl relative als auch absolute Zeitangaben. journalctl --since "1 hour ago" zeigt die letzte Stunde, während journalctl --since "2026-07-12 08:00:00" --until "2026-07-12 09:30:00" ein exaktes Fenster definiert. Auch symbolische Werte wie today, yesterday und now werden verstanden, was für schnelle Abfragen während einer Störung deutlich Zeit spart.
Ein wichtiger Stolperstein: journalctl interpretiert Zeitangaben standardmäßig in der lokalen Zeitzone des Systems, nicht in UTC. Bei Servern, die auf UTC laufen, während das Monitoring-Team in einer anderen Zeitzone denkt, führt das regelmäßig zu Verwirrung. Mit journalctl --utc --since "2026-07-12 06:00:00 UTC" lässt sich sowohl die Ausgabe als auch die Interpretation der Zeitfilter auf UTC umstellen. Die Kombination aus Zeitfenster und Unit-Filter, etwa journalctl -u mysql.service --since "30 min ago", ist das mit Abstand häufigste Muster bei der Vorfallsanalyse, weil sie die Datenmenge sofort auf das Relevante reduziert.
4. Nach Priorität filtern: -p und Schweregrade verstehen
Der Parameter -p beziehungsweise --priority filtert nach Syslog-Schweregrad und folgt den acht klassischen Stufen: emerg, alert, crit, err, warning, notice, info und debug. Wichtig zu wissen: journalctl -p err zeigt standardmäßig nicht nur exakt diese Stufe, sondern alle Einträge mit dieser Priorität und höherem Schweregrad, also err, crit, alert und emerg. Wer genau einen Schweregrad möchte, gibt einen Bereich mit zwei Werten an, etwa -p warning..err.
In der Praxis reduziert journalctl -p err -b die Ausgabe des aktuellen Boots meist drastisch, weil info- und debug-Rauschen komplett verschwindet, während echte Fehlermeldungen erhalten bleiben. Das ist der erste Befehl, den viele Administratoren nach einem unerklärlichen Ausfall ausführen. Zu beachten ist, dass viele Anwendungen ihre Log-Level nicht korrekt auf Syslog-Prioritäten abbilden, gerade selbstgeschriebene Dienste loggen häufig alles auf info, wodurch die Priority-Filterung dort weniger nützlich ist als bei gut gepflegten Systemdiensten.
# Show only errors and worse from the current boot
journalctl -p err -b
# Priority range: warning up to and including err
journalctl -p warning..err
# Numeric priority levels also work (0=emerg .. 7=debug)
journalctl -p 3
# Combine priority with unit and time window
journalctl -u nginx.service -p err --since "today"
# Kernel-only messages at crit level or higher
journalctl -k -p crit
5. Live mitlesen: -f und das Verhalten von tail -f
Die Option -f beziehungsweise --follow verhält sich wie tail -f bei klassischen Logdateien: journalctl gibt die letzten Zeilen aus und bleibt danach aktiv, um neue Einträge in Echtzeit anzuzeigen. Besonders nützlich beim gezielten Debugging ist die Kombination journalctl -u app.service -f, um live zu beobachten, wie ein Dienst auf einen Testaufruf reagiert, ohne im Rauschen anderer Units zu suchen. Mit -n lässt sich zusätzlich die Anzahl der initial angezeigten Zeilen steuern, etwa journalctl -u app.service -f -n 50 für die letzten 50 Zeilen plus Live-Stream.
Ein Unterschied zu tail -f: journalctl kann mehrere Units gleichzeitig live verfolgen und interleaved nach Zeitstempel ausgeben, was bei einer klassischen Logdatei ohne zusätzliche Tools wie multitail nicht möglich wäre. journalctl -f -u nginx -u php8.3-fpm zeigt beide Streams chronologisch vermischt in einem Terminal an. Für automatisierte Auswertung eignet sich --output json in Kombination mit -f, um jede neue Zeile als JSON-Objekt an ein Monitoring-Skript weiterzureichen. Wer den Live-Modus in einem Systemd-Timer oder Cronjob nutzen will, sollte statt -f lieber mit --cursor arbeiten, um nach einem Neustart des Auswertungsskripts nahtlos an der letzten Position weiterzulesen, ohne Einträge doppelt zu verarbeiten oder zu verpassen.
6. Persistentes versus flüchtiges Journal konfigurieren
Standardmäßig speichert systemd-journald auf vielen Distributionen das Journal nur flüchtig unter /run/log/journal/, einem tmpfs-Verzeichnis, das bei jedem Neustart geleert wird. Nach einem Reboot sind Logs vom Vorfall damit unwiederbringlich verloren, was bei der Root-Cause-Analyse eines Absturzes fatal sein kann. Ob das Journal persistent ist, zeigt journalctl --disk-usage zusammen mit einem Blick auf die Storage-Direktive in /etc/systemd/journald.conf.
Um das Journal dauerhaft zu machen, wird das Verzeichnis /var/log/journal/ angelegt und journald neu gestartet, oder alternativ Storage=persistent explizit in journald.conf gesetzt. Zusätzlich sollten SystemMaxUse und SystemMaxFileSize konfiguriert werden, damit das Journal nicht unkontrolliert die gesamte Festplatte füllt. Ohne diese Begrenzung kann journald theoretisch bis zu zehn Prozent des Dateisystems belegen, was auf kleinen Root-Partitionen schnell zu Speicherplatzproblemen führt.
# /etc/systemd/journald.conf
# Make the journal persistent across reboots and limit its disk footprint
[Journal]
Storage=persistent
Compress=yes
# Hard cap on total journal size on disk
SystemMaxUse=1G
# Keep at least this much free space on the filesystem
SystemMaxFileSize=128M
# Automatically remove entries older than this
MaxRetentionSec=1month
# Rate limit to avoid a noisy service flooding the journal
RateLimitIntervalSec=30s
RateLimitBurst=10000
7. Logs mehrerer Dienste im Vorfall korrelieren
Bei komplexen Vorfällen reicht es selten, nur einen Dienst zu betrachten, weil ein Fehler in der Datenbank sich über PHP-FPM bis zum Webserver fortpflanzt. journalctl erlaubt genau dafür die Kombination mehrerer -u-Filter mit einem gemeinsamen Zeitfenster, sodass Ereignisse chronologisch nebeneinander erscheinen: journalctl -u nginx -u php8.3-fpm -u mysql --since "09:14" --until "09:20" zeigt exakt, in welcher Reihenfolge die drei Dienste auf den Vorfall reagiert haben.
Für noch präzisere Korrelation über Container- und Cgroup-Grenzen hinweg hilft --identifier für Syslog-Identifier oder das Feld _SYSTEMD_CGROUP, das sich mit journalctl -o verbose anzeigen lässt und bei Docker- oder systemd-nspawn-Setups zeigt, aus welchem Container ein Eintrag stammt. Bei Anwendungen mit eigener Request-ID sollte diese ID konsequent ins strukturierte Log geschrieben werden, etwa über journalctl-kompatibles Structured Logging mit sd_journal_send, damit sich ein einzelner Request über mehrere Dienste hinweg mit einem einzigen grep nachvollziehen lässt.
# Correlate three services during a narrow incident window
journalctl -u nginx.service -u php8.3-fpm.service -u mysql.service \
--since "2026-07-12 09:14:00" --until "2026-07-12 09:20:00"
# Merge with kernel messages to rule out OOM kills
journalctl -u app.service -k --since "09:14" --until "09:20"
# Show verbose output to inspect cgroup and container fields
journalctl -u app.service -o verbose | grep -E "_SYSTEMD_CGROUP|CONTAINER_NAME"
# Trace a single request ID across services (structured logging required)
journalctl --since "09:14" --until "09:20" | grep "req_id=8f3a91"
8. Logs exportieren und mit Kollegen teilen
Um Logs an Kollegen weiterzugeben oder in einem Ticket zu dokumentieren, eignet sich --output json-pretty für lesbare, strukturierte Ausgabe oder --output export für das native binäre Austauschformat, das sich mit journalctl --file auf einem anderen System wieder importieren lässt. Für einen reinen Text-Export ohne Formatierungsschnickschnack reicht journalctl -u app.service --since today --no-pager > incident-2026-07-12.log, das sich problemlos per E-Mail oder in einem Ticket anhängen lässt.
Ein häufig übersehenes Feature ist journalctl -u app.service -o export | gzip > incident.journal.gz, das die vollständigen Metadaten inklusive aller Journal-Felder erhält, im Gegensatz zum reinen Text-Export, bei dem Felder wie _PID oder _SYSTEMD_UNIT verloren gehen. Beim Teilen sensibler Logs sollte vorher geprüft werden, ob Umgebungsvariablen oder Request-Bodies versehentlich mitgeloggt wurden, da journalctl standardmäßig alles unverändert ausgibt, was der Dienst geschrieben hat, inklusive potenzieller Zugangsdaten in Fehlermeldungen.
{
"__CURSOR": "s=8f2c1e...;i=5d3a;b=91a7f4...",
"__REALTIME_TIMESTAMP": "1752307140000000",
"_SYSTEMD_UNIT": "app.service",
"_PID": "48213",
"_UID": "1001",
"PRIORITY": "3",
"SYSLOG_IDENTIFIER": "app",
"MESSAGE": "Database connection timeout after 5000ms",
"_HOSTNAME": "shop-web-02"
}
9. journalctl im direkten Vergleich zu klassischen Logdateien
Der Umstieg von grep über Textdateien auf journalctl-Filter ist keine reine Geschmacksfrage, sondern bringt messbare Vorteile bei Geschwindigkeit, Genauigkeit und Nachvollziehbarkeit. Die folgende Tabelle stellt typische Aufgaben und die jeweils empfohlene Herangehensweise gegenüber.
| Aufgabe | Klassisch (Textlog) | journalctl | Vorteil |
|---|---|---|---|
| Nach Dienst filtern | grep nginx /var/log/syslog |
journalctl -u nginx |
Exakte Zuordnung ohne Namenskollisionen |
| Zeitraum eingrenzen | sed -n '/08:00/,/09:00/p' |
--since --until |
Robust gegen Formatwechsel im Log |
| Nach Schweregrad filtern | grep -i "error\|crit" |
-p err |
Erfasst echte Priorität, nicht nur Text |
| Nach Reboot noch verfügbar | Rotiert oder gelöscht | Storage=persistent |
Logs überstehen Absturz und Neustart |
| Mehrere Dienste live verfolgen | multitail nötig |
journalctl -f -u a -u b |
Kein Zusatztool, chronologisch interleaved |
In der Praxis zeigt sich der größte Zeitgewinn bei der Kombination mehrerer Filter in einem einzigen Befehl: Wo klassisch mehrere Pipes mit grep, awk und sed nötig wären, reicht bei journalctl eine Zeile mit -u, -p und --since. Das reduziert nicht nur Tippaufwand, sondern auch die Fehleranfälligkeit unter Stress während eines laufenden Incidents.
Mironsoft
Server-Administration, Monitoring und Incident-Response für Linux-Umgebungen
Logging-Setup, das im Ernstfall wirklich hilft?
Wir richten persistentes Journal-Logging ein, korrelieren Logs über eure gesamte Service-Landschaft und bauen belastbare Monitoring- und Alerting-Pipelines für eure Magento- und Linux-Server.
Journal-Audit
Persistenz, Speicherlimits und Rate-Limiting korrekt konfigurieren
Incident-Runbooks
journalctl-Abfragen für wiederkehrende Störungsmuster dokumentieren
Log-Aggregation
Journal-Export in zentrale Log-Stacks wie Loki oder Elasticsearch
10. Zusammenfassung
journalctl löst das Grundproblem verstreuter Textlogs, indem es alle systemd-Logs strukturiert an einer Stelle bündelt und über -u, --since/--until, -p und -f gezielt filterbar macht. Die Kombination aus Unit-Filter und Zeitfenster ist das mit Abstand häufigste Muster bei der Vorfallsanalyse, während die Priority-Filterung info-Rauschen zuverlässig ausblendet. Ohne persistentes Journal über Storage=persistent in journald.conf gehen Logs bei jedem Neustart verloren, was gerade bei Absturzanalysen fatal ist.
Bei komplexen Vorfällen mit mehreren beteiligten Diensten liefert die Kombination mehrerer -u-Filter mit einem gemeinsamen Zeitfenster eine chronologisch korrekte Gesamtsicht, die mit klassischen Textlogs nur über Zusatztools wie multitail erreichbar wäre. Für die Weitergabe an Kollegen oder die Dokumentation in Tickets eignen sich --output json-pretty für Lesbarkeit und --output export, wenn die vollständigen Metadaten erhalten bleiben sollen.
journalctl effektiv nutzen, das Wichtigste auf einen Blick
Filtern nach Unit und Zeit
journalctl -u <service> --since --until ist das Standardmuster für jede gezielte Log-Analyse.
Priorität und Live-Modus
-p err blendet Rauschen aus, -f verfolgt mehrere Units live und chronologisch interleaved.
Persistenz konfigurieren
Storage=persistent plus SystemMaxUse sichern Logs über Neustarts hinweg, ohne die Platte zu fluten.
Export und Korrelation
Mehrere -u-Filter kombinieren, mit --output export vollständige Metadaten für Kollegen sichern.