Das Problem
journalctl kann Filter mit UND und ODER verknüpfen, kennt aber kein NOT. Es
gibt keine Option, um einen lauten Dienst, einen Syslog-Identifier oder eine
wiederkehrende Meldung auszublenden. Der übliche Umweg ist
journalctl | grep -v. Dabei gehen Farben und Pager verloren, solange
SYSTEMD_COLORS nicht gesetzt ist, grep trifft Zeilen innerhalb mehrzeiliger
Meldungen, und -n 20 zeigt weniger als 20 Zeilen, weil grep erst nach dem
Zählen durch journalctl filtert. Der andere Umweg ist
journalctl -o json | jq 'select(...)'. Das filtert korrekt, gibt aber rohes
JSON aus.
Der Bedarf ist belegt:
- systemd/systemd#2720, "RFE: add NOT operator to journal matching", ist seit 2016 offen und hat 131 Reaktionen und 22 Kommentare. Die Antwort des Maintainers war, NOT stehe auf der TODO-Liste, sei mit den Journal-Indizes aber schwer umzusetzen. Die Anfrage geht auf freedesktop-Bug 55868 aus dem Jahr 2012 zurück.
- Die Super-User-Frage "How to exclude journalctl entries using a filter?" hat einen Score von 26 und etwa 39.000 Aufrufe.
- systemd 256 hat
-T/--exclude-identifiereingeführt. Das deckt nur Syslog-Identifier ab und fehlt in Ubuntu 24.04 (systemd 255), Debian 12 (252) und RHEL 9 (252).
Wie es funktioniert
journalctl-not reicht alle
journalctl-Optionen durch, führt den Befehl mit -o json aus, verwirft jeden
Eintrag, auf den ein Ausschluss passt, und gibt den Rest aus. Die Ausschlüsse
sind FIELD!=VALUE, --exclude-unit und --exclude-user-unit (mit denselben
Feldern, die journalctl -u verwendet), -T/--exclude-identifier wie in
systemd 256 und --exclude-grep für einen regulären Ausdruck auf der Meldung.
Ein Eintrag wird ausgeblendet, sobald ein Ausschluss passt.
Die Textausgabe ist eine Portierung des Formatierungscodes von systemd
(logs-show.c und strip_tab_ansi()). Für die unterstützten Ausgabemodi ist
das Ergebnis deshalb byte-genau dasselbe wie bei journalctl. -n N zählt die
Einträge, die nach den Ausschlüssen übrig bleiben: Das Werkzeug liest das
Journal rückwärts, bis es N davon hat. Mit -f gibt es diese aus und folgt dann
ab dem neuesten Eintrag.
Im folgenden Beispiel wurden sieben Einträge mit systemd-cat geschrieben. Die
Zeilen "health check ok" haben Debug-Priorität (7):
$ journalctl -t demo-app -t demo-sync --no-hostname
Nov 01 06:45:23 demo-app[97742]: request took 812 ms
Nov 01 06:45:23 demo-app[97746]: health check ok
Nov 01 06:45:23 demo-app[97750]: health check ok
Nov 01 06:45:23 demo-app[97754]: upstream timed out
Nov 01 06:45:23 demo-sync[97758]: Starting nightly sync
Nov 01 06:45:23 demo-app[97762]: disk full, retrying
Nov 01 06:45:23 demo-app[97766]: health check ok
$ journalctl-not -t demo-app -t demo-sync -n 3 PRIORITY!=7 -T demo-sync --no-hostname
Nov 01 06:45:23 demo-app[97742]: request took 812 ms
Nov 01 06:45:23 demo-app[97754]: upstream timed out
Nov 01 06:45:23 demo-app[97762]: disk full, retrying
-n 3 liefert die letzten drei Einträge, die übrig bleiben. Dasselbe -n 3
mit nachgeschaltetem grep -v hätte eine Zeile ausgegeben. Das Werkzeug
braucht Python 3.9 oder neuer und hat keine Abhängigkeiten außerhalb der
Standardbibliothek.
Tests
Die Unit-Tests decken das Parsen der Argumente, die Ausschlussregeln, die
Darstellung von Zeitstempeln, mehrzeiligen Meldungen, Binärfeldern und Farben
sowie vollständige Läufe gegen ein Ersatz-journalctl ab, das eine JSON-Fixture
abspielt. Diese Läufe prüfen, dass -n die verbleibenden Einträge zählt und
dass -f nach dem neuesten Cursor weiterliest.
tests/golden.sh schreibt Testeinträge ins echte Journal und vergleicht
journalctl-not ohne Ausschlüsse byte-genau mit journalctl: in acht
Ausgabemodi, mit Farben, in zwei Zeitzonen sowie über das gesamte Journal der
letzten sechs Stunden und das Kernel-Log. Außerdem vergleicht es Ausschlüsse
mit gleichbedeutenden journalctl-Filtern, zum Beispiel PRIORITY!=7 mit
-p info. Das CI führt die Unit-Tests und den Golden-Test auf Ubuntu 24.04
(systemd 255) mit Python 3.9, 3.12 und 3.13 aus. Beim Schreiben des Golden-Tests
fielen zwei Eigenheiten von journalctl 255 auf, die journalctl-not nicht
nachbildet: Mit -n N --until T und weniger als N Treffern gibt journalctl auch
Einträge nach T aus, und mit --grep und -n gibt es sie in umgekehrter
Reihenfolge aus, die neuesten zuerst.
Grenzen
- Unterstützt sind nur die Ausgabemodi
short,short-precise,short-iso,short-iso-precise,short-full,short-unix,short-monotonic,catundjson. Andere werden mit einem Fehler abgelehnt. -x/--catalogwird mit einer Warnung ignoriert. Mit Farben fügt journalctl anklickbare Links ein und hebt Treffer von--grephervor, journalctl-not nicht.- Monats- und Wochentagsnamen sind immer englisch.
- Die Ausschlüsse laufen in Python, nachdem journalctl die Einträge gelesen hat.
Die Ausgabe eines ganzen Journals mit 600.000 Zeilen dauert etwa 3,5-mal so
lange wie mit journalctl. Bei
-foder-n 100fällt der Unterschied nicht auf. FIELD!=VALUEvergleicht den ganzen Wert und behält Einträge, die das Feld nicht haben.- Die Formatierung folgt systemd 255. Neuere Versionen können Details wie Farben ändern.
Code und Installationsanleitung liegen unter github.com/Jwrede/journalctl-not.