Gibt es eine Möglichkeit, journalctl so zu gestalten, dass es Protokolle vom letzten Ausführen von foo.service anzeigt?


15

Dies interessiert mich besonders, um die Ausgabe von Oneshot-Diensten zu betrachten, die auf einem Timer ausgeführt werden. Das --unitFlag ist in der Nähe, verknüpft jedoch alle Ausführungen des Dienstes miteinander. Der naheliegendste Weg, den ich mir vorstellen kann, ist das Filtern nach PID, aber das macht mir Sorgen über die Wiederverwendung / die Dienste von PID, und das Abrufen der letzten PID ist ziemlich unpraktisch. Gibt es eine andere Kennung, die einer einzelnen Ausführung eines Dienstes entspricht und die ich zum Filtern der Protokolle verwenden könnte?

EDIT: Ich würde gerne ein autoritäres "Nein" akzeptieren, wenn das die richtige Antwort ist.

Antworten:


5

Seit der systemdVersion 232haben wir das Konzept der Aufruf-ID. Jedes Mal, wenn eine Einheit ausgeführt wird, verfügt sie über eine eindeutige 128-Bit-Aufruf-ID. Im Gegensatz zu MainPIDdem, was recycelt werden kann oder ActiveEnterTimestampProbleme bei der Lösung haben kann, ist dies eine ausfallsichere Methode, um das gesamte Protokoll eines bestimmten Systemaufrufs abzurufen.

So erhalten Sie die neueste Aufruf-ID einer Einheit

$ systemctl show --value -p InvocationID openipmi
bd3eb84c3aa74169a3dcad2af183885b

Um das Journal des letzten Aufrufs zu erhalten, beispielsweise openipmi, ob er fehlgeschlagen ist oder nicht, können Sie den einen Liner verwenden

$ journalctl _SYSTEMD_INVOCATION_ID=`systemctl show -p InvocationID --value openipmi.service`
-- Logs begin at Thu 2018-07-26 12:09:57 IDT, end at Mon 2019-07-08 01:32:50 IDT. --
Jun 21 13:03:13 build03.lbits openipmi[1552]:  * Starting ipmi drivers
Jun 21 13:03:13 build03.lbits openipmi[1552]:    ...fail!
Jun 21 13:03:13 build03.lbits openipmi[1552]:    ...done.

(Beachten Sie, dass das --valueseit verfügbar ist systemd 230, älter als InvocationID)


Wenn jemand versucht, dies zu untersuchen: journalctl --user -u UNITFILE -f -o json-prettykönnte hilfreich sein; Sie suchen vor allem nach MESSAGEFeldern. Ich habe herausgefunden, dass Sie möglicherweise auch benötigen USER_INVOCATION_IDund dass einigen Nachrichten keine Aufruf-ID zugeordnet ist, sodass sie über diesen Mechanismus nicht gefiltert werden können. Ich
weiß

14

Ich bin nicht sicher, welcher Zeitstempel am sinnvollsten ist, aber das funktioniert für mich. Hoffentlich gibt es eine bessere Möglichkeit, mit den Zeitstempeln von zu arbeiten, systemctl showals awk - konnte nicht herausfinden, wie das Format der Zeitstempel gesteuert werden kann.

unit=foo.service

ts=$(systemctl show -p ActiveEnterTimestamp $unit)

echo $ts
ActiveEnterTimestamp=Fri 2016-11-11 12:30:01 MST

journalctl -u $unit --since "$(echo $ts | awk '{print $2 $3}')"

Nur für den Fall, dass es jemand als Einzeiler braucht: journalctl - seit " systemctl show -p ActiveEnterTimestamp thermo.service | awk '{print $2 \" \" $3}'" -fu thermo.service | weniger
DimanNe

Sie können auch verwenden systemctl show -p ActiveEnterTimestamp --value $unit, so gibt es keine Notwendigkeit für zusätzliche awk
Karlicoss

4

Sie können das Startflag verwenden, um nur die Protokolle von diesem Start abzurufen. zum Beispiel

journalctl _SYSTEMD_UNIT=avahi-daemon.service -b 5

2
Dies ähnelt dem, was ich möchte, funktioniert jedoch nicht in Situationen wie: 1) wenn der Computer seit dem letzten Ausführen des Dienstes neu gestartet wurde oder 2) wenn der Dienst seit dem letzten Start mehrmals ausgeführt wurde.
Jack O'Connor

Ich bin mir nicht sicher, warum es im ersten Fall nicht funktioniert. Wenn es neu gestartet wurde, wird es auch neu gestartet. Sie müssen nur zu diesem bestimmten Boot gehen und Ihre Informationen abrufen. In Bezug auf die Sekunde ... hast du recht. Die Geräuschprotokolle hängen davon ab, wie oft der Dienst neu gestartet wurde. Sobald Sie Ihre Service-PID entdeckt haben, können Sie sie mit dem Argument _PID = XXX filtern. Die Chancen, dieselbe PID für denselben Dienst im selben Bootzyklus erneut zu verwenden, sind ... keine Ahnung ... sondern nahezu unmöglich.
Nikolaidis Fotis

Ich interessiere mich für die Verarbeitung von Diensten, die nicht unbedingt beim Booten ausgeführt werden, entweder weil sie auf Timern basieren oder weil es sich um einmalige Befehle handelt.
Jack O'Connor

3

Diese könnten Ihnen helfen:

  • journalctl -u foo.service | Schwanz -n 2

    oder ersetzen Sie 2 durch die erwartete Anzahl von Zeilen

  • journalctl -u foo.service --since = ' 2016-04-11 13:00:00 '

Sie können sie auch kombinieren, um zuerst den Zeitstempel der letzten Laufzeit abzurufen, und diesen Zeitstempel dann mit der Option --since verwenden.


Dies fühlt sich an wie eine Problemumgehung ähnlich dem PID-Ansatz, ist jedoch sehr manuell. Wenn mein Dienst über viele Sekunden ausgeführt wird und viele Protokollzeilen ausspuckt, muss ich nach der ersten Zeile suchen, deren Startzeitstempel mir wichtig ist. Das funktioniert in einem Skript nicht sehr gut.
Jack O'Connor

3

Sie können mit Journalctl Feldfilter verwenden. Z.B

journalctl _PID=1234

Eine Liste aller verfügbaren Felder erhalten Sie mit:

journalctl --fields --unit kubelet

Ein verfügbares Feld ist _PID.

Mit pidofoder können Sie die PID eines laufenden Prozesses ermittelnsystemctl show --property MainPID <SERVICE_NAME>

So erhalte ich die Protokolle aus dem aktuellen Kubernetes-Kubelet-Prozess:

# journalctl --unit kubelet _PID=$(systemctl show --property MainPID kubelet 2>/dev/null | cut -d= -f2) | head

Jetzt sag mir warum ich Kubernetes so schwer zu installieren habe :-(


Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.