C'è un modo per fare in modo che journalctl mostri i registri "dall'ultima volta in cui è stato eseguito foo.service"?


15

Sono particolarmente interessato a questo per guardare l'output dei servizi oneshot eseguiti su un timer. La --unitbandiera è vicina, ma concatena tutte le corse del servizio insieme. Il modo più ovvio a cui riesco a pensare sarebbe quello di filtrare su PID, ma questo mi fa preoccupare del riutilizzo / servizi PID che si biforcano e ottenere l'ultimo PID è piuttosto scomodo. Esiste un altro identificatore che corrisponde a una singola esecuzione di un servizio che è possibile utilizzare per filtrare i registri?

EDIT: accetterei felicemente un autorevole "no" se questa è la vera risposta.

Risposte:


6

Dalla systemdversione 232, abbiamo il concetto di ID di invocazione. Ogni volta che un'unità viene eseguita, ha un ID di chiamata a 128 bit univoco. Diversamente da MainPIDquale può essere riciclato o ActiveEnterTimestampche può avere problemi di risoluzione, è un modo sicuro per ottenere tutto il registro di una particolare chiamata di unità di sistema.

Per ottenere l'ultimo ID di invocazione di un'unità

$ systemctl show --value -p InvocationID openipmi
bd3eb84c3aa74169a3dcad2af183885b

Per ottenere il diario dell'ultima invocazione, per esempio openipmi, se ha fallito o no, è possibile utilizzare un solo liner

$ 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.

(Nota che --valueè disponibile da systemd 230, più vecchio di InvocationID)


Se qualcuno sta cercando di indagare su questo: journalctl --user -u UNITFILE -f -o json-prettypotrebbe essere utile; stai cercando MESSAGEcampi in particolare. Ho scoperto che potresti anche averne bisogno USER_INVOCATION_IDe che alcuni messaggi non hanno alcun ID di chiamata associato, quindi non possono essere filtrati attraverso questo meccanismo. Non so perché, forse la mia registrazione non è configurata
correttamente

14

Non sono sicuro di quale marca temporale abbia più senso, ma questo funziona per me. Speriamo che ci sia un modo migliore di lavorare con i timestamp systemctl showrispetto a awk - non riesco a capire come controllare il formato dei timestamp.

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}')"

Nel caso in cui qualcuno ne abbia bisogno come one-liner: journalctl --since " systemctl show -p ActiveEnterTimestamp thermo.service | awk '{print $2 \" \" $3}'" -fu thermo.service | meno
DimanNe

Puoi anche usare systemctl show -p ActiveEnterTimestamp --value $unit, quindi non c'è bisogno di extra awk
karlicoss

4

È possibile utilizzare il flag di avvio per recuperare solo i registri da tale avvio. per esempio

journalctl _SYSTEMD_UNIT=avahi-daemon.service -b 5

2
Questo è simile a quello che voglio, ma non funziona in situazioni come: 1) se il computer è stato riavviato dall'ultima volta in cui è stato eseguito il servizio, oppure 2) se il servizio è stato eseguito più volte dall'ultimo avvio.
Jack O'Connor,

Non sono sicuro del motivo per cui non funziona per il primo caso. Se è stato riavviato, verrà riavviato anche. Devi solo andare a quello specifico avvio e recuperare le tue informazioni. Per quanto riguarda il secondo ... hai ragione. I log del rumore dipendono dal numero di volte in cui il servizio è stato riavviato. Ma una volta individuato il pid del servizio, è possibile filtrarlo utilizzando l'argomento _PID = XXX. Le possibilità di riutilizzare lo stesso pid per lo stesso servizio nello stesso ciclo di avvio sono ..... nessuna idea ... ma piuttosto impossibili.
Nikolaidis Fotis,

Sono interessato a gestire servizi che non sono necessariamente eseguiti all'avvio, sia perché sono su timer o perché sono comandi una tantum.
Jack O'Connor,

3

Questi potrebbero aiutarti:

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

    o sostituire 2 con il numero previsto di righe

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

Puoi anche combinarli per ottenere prima il timestamp dell'ultimo tempo di esecuzione, quindi utilizzare quel timestamp con l'opzione --since.


Sembra una soluzione simile all'approccio PID, ma è molto manuale. Se il mio servizio dura molti secondi e sputa molte linee di log, devo andare a cercare la prima riga che ha il timestamp iniziale a cui tengo. Non funzionerà molto bene in una sceneggiatura.
Jack O'Connor,

3

È possibile utilizzare i filtri di campo con Journalctl. Per esempio

journalctl _PID=1234

Ottieni un elenco di tutti i campi disponibili usando:

journalctl --fields --unit kubelet

Un campo disponibile è _PID.

È possibile ottenere il PID di un processo in esecuzione utilizzando pidofosystemctl show --property MainPID <SERVICE_NAME>

Ecco quindi come ottengo i log dall'attuale processo kubelet di Kubernetes:

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

Ora dimmi perché Kubernetes è così difficile da installare :-(


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.