journalctl: analizzare i log di systemd e conservarli nel tempo

Pubblicato il 20 min di lettura

Finestre temporali, filtri per unit, priorità e schemi di ricerca: come ritagliare in tre o quattro comandi esattamente la porzione di log che riguarda il guasto. In più un journal che sopravvive ai riavvii, con i messaggi di errore riportati alla lettera.

Un server su cui qualcosa non va ha quasi sempre già messo per iscritto quello che è successo. Il problema non è l'informazione che manca, ma la quantità in cui si trova. Chi lancia journalctl senza argomenti finisce all'inizio del journal e sfoglia settimane di messaggi vecchi. Questa guida mostra come ritagliare, in tre o quattro comandi, esattamente la porzione che riguarda il guasto.

L'articolo creare un servizio systemd presenta le forme di base -u, -b e -f. Qui si parla di tutto quello che viene dopo: finestre temporali, filtri, priorità, formati di output, la conservazione permanente del journal, i limiti di dimensione, i messaggi del kernel e schemi di ricerca già pronti.

Tutte le indicazioni si riferiscono a Debian 13 (trixie), Debian 12 (bookworm), Ubuntu 24.04 LTS e Ubuntu 22.04 LTS. I comandi sono scritti per l'esecuzione come root. Se lavori come utente normale, anteponi sudo a ogni comando.

Prima di cambiare qualcosa: la via del ritorno

Leggere il journal non comporta rischi, nessun comando di ricerca di questo articolo modifica qualcosa sul sistema. Le cose rischiose sono esattamente tre, e arrivano tutte più avanti.

Un filesystem pieno. Senza un limite proprio il journal occupa fino al dieci per cento del filesystem, con un tetto di quattro gigabyte. Su un disco piccolo una /var piena è la strada più breve verso un server che non accetta più nessun accesso.

Un errore di battitura nella configurazione. systemd ignora le chiavi sconosciute invece di fermare il servizio. Il tuo limite resta scritto nel file, ma non ha alcun effetto, e nessuno te lo viene a dire.

Una pulizia troppo affrettata. journalctl --vacuum-time=1d cancella in modo irreversibile, comprese le prove che stai cercando proprio in quel momento.

La via di fuga per il caso peggiore: sui server root KVM e sui server dedicati di KernelHost non esistono IPMI né iDRAC. L'accesso che funziona anche senza rete è la console VNC nell'area clienti. È agganciata al livello di virtualizzazione, oppure al collegamento stesso, non allo stack di rete del sistema guest. Accedi lì una volta prima, e assicurati di conoscere la password di root.

Ricognizione in cinque comandi

systemctl --version | head -n 1
systemctl is-active systemd-journald
journalctl --disk-usage
ls -d /var/log/journal /run/log/journal
df -h /var

Il quarto comando è il più importante: risponde alla domanda se il tuo journal sopravvive a un riavvio, e per la directory che di volta in volta non esiste segnala No such file or directory. Tutte le modifiche di questo articolo finiranno più avanti in un file dedicato sotto /etc/systemd/journald.conf.d/. La /etc/systemd/journald.conf fornita dalla distribuzione resta intatta, e per tornare indietro bastano due comandi: cancellare il file, riavviare il servizio.

Restringere la finestra temporale invece di scorrere

Quasi ogni guasto ha un timestamp. L'analisi comincia da lì, non dal nome del servizio.

journalctl --since "-30min"
journalctl --since "2026-09-02 03:10" --until "2026-09-02 03:20"
journalctl --since yesterday --until today

--since e --until hanno le forme brevi -S e -U. Come indicazione di tempo journalctl accetta valori assoluti nella forma 2026-09-02 03:10:00, date senza orario (vale allora la mezzanotte), le parole chiave yesterday, today, tomorrow e now oltre a indicazioni relative come -1h, -30min o 2 days ago.

Qui si nasconde una trappola che costa parecchio tempo: journalctl lavora nell'ora locale del server, mentre le applicazioni scrivono spesso i log in UTC. Chi prende un timestamp da un log applicativo e lo infila in --since senza controllare, d'estate cerca due ore accanto all'evento. Verifica il fuso, oppure fatti mostrare tutto direttamente in UTC:

timedatectl
journalctl --since "2026-09-02 01:10" --until "2026-09-02 01:20" --utc --no-pager

Verifica: se torna -- No entries --, o la finestra è troppo stretta oppure il fuso è sbagliato. Allarga la finestra a un'ora come prova, prima di dubitare dei filtri.

Gli avvii del sistema come finestra temporale

Spesso la porzione giusta non è un intervallo di orario, ma un avvio del sistema. -b senza valore indica quello in corso, -b -1 quello precedente.

journalctl --list-boots --no-pager
journalctl -b -1 -p err --no-pager

La lista mostra una riga per ogni avvio con un indice, quello in corso porta lo 0. Se compare solo quella riga, il journal probabilmente non viene conservato in modo permanente. In quel caso -b -1 risponde su Debian 13 con No journal boot entry found for the specified boot (-1) e su Ubuntu 24.04 con No journal boot entry found from the specified boot offset (-1). Non è un difetto, è l'avviso che lì non c'è niente da recuperare.

Filtrare per servizio, processo e priorità

La unit, e perché il nome deve essere esatto

journalctl -u nginx.service --since "-2h" --no-pager

-u confronta per uguaglianza, non per somiglianza. Ne nasce un errore particolarmente sgradevole, perché non produce alcun messaggio di errore: journalctl -u mysql su un sistema Debian con MariaDB restituisce -- No entries --, anche se il journal è pieno di messaggi del database. Lì mysql.service è soltanto un nome alternativo di mariadb.service. systemctl risolve questi nomi alternativi, il journal invece salva sotto il nome vero. Ottieni quindi una risposta sbagliata che non sembra affatto un errore.

Il nome vero lo ricavi dal journal stesso. -F elenca tutti i valori che un campo ha mai assunto lì dentro:

journalctl -F _SYSTEMD_UNIT | sort | grep -i sql

-u accetta inoltre dei pattern, il che disinnesca il problema:

journalctl -u "mysql*" -u "mariadb*" -n 60 --no-pager

La stessa verifica conviene farla su Ubuntu 24.04 per SSH, perché lì il servizio parte tramite socket activation e gli accessi non finiscono per forza sotto il nome che ti aspetti:

journalctl -F _SYSTEMD_UNIT | grep -i ssh

L'identificatore invece della unit

Oltre alla unit esiste l'identificatore del mittente, cioè quello che il syslog classico registra come nome del programma. Il filtro relativo è -t:

journalctl -t sshd -t sshd-session -n 50 --no-pager

Perché due? Dalla versione 9.8 OpenSSH sposta le sessioni in un processo separato, sshd-session. Su Debian 13 (OpenSSH 10.0) sotto -t sshd resta quindi solo l'informazione che il servizio è in ascolto, mentre ogni accesso finisce sotto -t sshd-session. Debian 12 (9.2), Ubuntu 24.04 (9.6) e Ubuntu 22.04 (8.9) non conoscono questa suddivisione. Chi su Debian 13 filtra solo -t sshd considera tranquillo un server su cui in quel momento viene registrato ogni singolo tentativo. Più robusta è la strada che passa per la unit, perché i processi figli appartengono alla stessa:

journalctl -u ssh --since "-24h" --no-pager

Campi qualsiasi, e come vengono combinati

Ogni voce di log porta con sé dei campi che puoi scrivere direttamente come filtro, per esempio _COMM (nome del programma), _PID, _UID, _SYSTEMD_UNIT o _TRANSPORT. Le regole di combinazione vengono spesso date per scontate nel modo sbagliato:

  • Due filtri su campi diversi si combinano con un E logico.
  • Due filtri sullo stesso campo si combinano con un O logico.
  • Un singolo segno più tra due gruppi collega i gruppi con un O logico.
journalctl _SYSTEMD_UNIT=ssh.service _UID=0 --since "-1h" --no-pager
journalctl _SYSTEMD_UNIT=ssh.service + _SYSTEMD_UNIT=nginx.service --since "-1h" --no-pager

I nomi dei campi sono in maiuscolo e il confronto avviene sul valore completo. Un journalctl unit=nginx non è quindi un filtro su una sottostringa, ma un errore di sintassi che journalctl liquida con Failed to add match.

Le priorità

Ogni voce di log porta un livello di urgenza da 0 a 7. -p filtra su quello, includendo sempre tutti i livelli più urgenti: -p err mostra anche crit, alert ed emerg.

LivelloNomeSignificato
0emergSistema inutilizzabile
1alertServe un intervento immediato
2critErrore critico in un componente
3errErrore, un'operazione è rimasta incompiuta
4warningAvviso, il funzionamento prosegue
5noticeDegno di nota, ma normale
6infoNormale messaggio di esercizio
7debugSolo per la ricerca degli errori
journalctl -b -p err --no-pager
journalctl -u nginx.service -p 2..4 --since "-24h" --no-pager

E adesso l'insidia su cui il filtro per priorità si arena regolarmente: per impostazione predefinita, quello che un servizio scrive sullo standard output finisce nel journal come info, anche se stava sullo standard error. Un programma che stampa un'eccezione con tanto di stacktrace appare così come un innocuo messaggio di esercizio, e -p err lo nasconde. Un livello adeguato lo ottengono solo i programmi che scrivono direttamente sull'interfaccia del journal oppure antepongono alle proprie righe un prefisso syslog come <3>. Per i servizi scritti da te conviene quindi filtrare per unit e per testo, mentre per i servizi di sistema e per il kernel -p è invece del tutto utilizzabile.

Ricerca nel testo

journalctl -u nginx.service --since "-24h" --grep "upstream timed out" --no-pager

--grep (forma breve -g) cerca esclusivamente nel testo del messaggio, non negli altri campi. Le maiuscole e le minuscole vengono ignorate automaticamente finché il pattern è scritto tutto in minuscolo; appena compare una lettera maiuscola il confronto diventa esatto. Puoi forzare l'uno o l'altro comportamento con --case-sensitive=yes o --case-sensitive=no. Le espressioni regolari sono ammesse, quindi la barra verticale funziona come un O logico.

Seguire il log in tempo reale

-f si aggancia alla fine del journal e mostra le righe nuove non appena arrivano. Ha senso quasi solo insieme a un filtro, altrimenti ti scorre davanti mezzo sistema. -n stabilisce quante righe passate compaiono per prime; senza indicazione sono dieci. Si esce con Ctrl+C.

journalctl -u nginx.service -f -n 100
journalctl -f -u nginx.service -u php8.2-fpm.service
journalctl -f -p warning

La procedura abituale per un errore riproducibile: in una prima sessione segui il log, in una seconda provochi l'errore. Con righe molto larghe aiuta -o cat, perché così compare solo il testo del messaggio, senza timestamp né mittente.

Verifica: se al momento di provocare l'errore non arriva proprio niente, il servizio non scrive nel journal ma in un file proprio. Con i web server e i database è la norma. La strada passa allora per la configurazione dell'applicazione, non per altre opzioni di journalctl.

Formati di output

Il formato standard è pensato per una persona davanti al terminale. Per il confronto con altri log, per le pipe e per le analisi ce ne sono di più adatti. Si cambia con -o:

FormatoA cosa serve
shortimpostazione predefinita, ora locale precisa al secondo
short-isotimestamp secondo ISO 8601 con lo scostamento di fuso, ideale per il confronto
short-precisecome short, ma con le frazioni di secondo
short-monotonicsecondi trascorsi dall'avvio del sistema, buono per i problemi di boot
short-unixtempo Unix, comodo per fare calcoli
catsolo il testo del messaggio, pensato per le pipe
verbosetutti i campi di una voce, così impari i nomi dei campi
json-prettyleggibile dalla macchina e comunque leggibile
journalctl -u ssh.service -n 1 -o verbose --no-pager

Questo singolo comando vale più di qualsiasi elenco di campi in una guida: vedi quali campi portano davvero le tue voci di log, e ognuno di essi lo puoi poi usare come filtro. Quattro opzioni completano il quadro:

  • --no-pager disattiva il pager. Negli script e prima di ogni pipe è d'obbligo, altrimenti la chiamata resta in attesa di un tasto che nessuno preme.
  • -r inverte l'ordine, le righe più recenti stanno in alto.
  • -e salta subito alla fine dentro il pager.
  • -x aggiunge ai messaggi propri di systemd un testo esplicativo preso dal catalogo.

Con --output-fields= puoi ridurre l'output ai soli campi che ti interessano. Funziona solo con verbose, json e i formati affini:

journalctl -u ssh.service --since "-1h" -o json --output-fields=MESSAGE,_PID --no-pager

Conservare il journal oltre i riavvii

Se il journal sopravvive a un riavvio lo decide l'impostazione predefinita Storage=auto, secondo una regola semplice: se /var/log/journal esiste, si scrive lì e tutto viene conservato. Se non esiste, tutto finisce nella RAM sotto /run/log/journal e sparisce al riavvio successivo. Non fidarti della distribuzione, tra varianti di installazione e immagini cloud si incontrano entrambe le situazioni. Un journal nella RAM è la spiegazione più frequente del fatto che dopo un crash nessuno sa più dire che cosa fosse successo prima.

Se decidi di cambiare, imposta il limite nello stesso passaggio. Per esperienza, dopo non lo fa più nessuno:

mkdir -p /etc/systemd/journald.conf.d
cat > /etc/systemd/journald.conf.d/10-kh-journal.conf <<'EOF'
[Journal]
Storage=persistent
SystemMaxUse=500M
SystemKeepFree=1G
MaxRetentionSec=1month
EOF
systemctl restart systemd-journald
journalctl --flush

Storage=persistent crea la directory da solo, un mkdir non serve. journalctl --flush trasferisce quello che si trova ancora in /run dentro /var/log/journal.

Verifiche, in questo ordine:

systemd-analyze cat-config systemd/journald.conf | grep -v '^#'
ls -d /var/log/journal
journalctl -u systemd-journald -b -n 20 --no-pager

Il primo comando mostra la configurazione effettiva, quella che nasce dal file principale e da tutti i file aggiuntivi, cioè quello che il servizio ha letto davvero. Il terzo è il test per gli errori di battitura: se lì compare una riga con Unknown key, la tua impostazione non ha effetto. A seconda della versione di systemd suona Unknown key name 'SystemMaxUsage' in section 'Journal', ignoring oppure Unknown key 'SystemMaxUsage' in section [Journal], ignoring.

La prova definitiva è un riavvio vero. Dopo, journalctl --list-boots deve mostrare almeno due righe e journalctl -b -1 -n 20 deve restituire delle voci. Se preferisci creare la directory a mano, segui la strada qui sotto. La chiamata di systemd-tmpfiles imposta proprietario, permessi e le liste di accesso che consentono la lettura ai gruppi giusti:

mkdir -p /var/log/journal
systemd-tmpfiles --create --prefix /var/log/journal
systemctl restart systemd-journald

Leggere senza root

Un utente normale vede solo i propri messaggi e riceve in più l'avviso Hint: You are currently not seeing messages from other users and the system. con il rimando ai gruppi che possono leggere tutto. Su Debian e Ubuntu di solito è adm:

usermod -aG adm nomeutente

Verifica: l'appartenenza al gruppo vale solo a partire da un accesso nuovo. Quindi esci, rientra, poi id -nG e journalctl -n 5. Se l'avviso non compare più e si vedono i messaggi di sistema, ha funzionato.

Limitare la dimensione prima che lo faccia il disco

ChiaveEffetto
SystemMaxUselimite massimo per il journal sul disco
SystemKeepFreespazio che il journal lascia libero sul disco
RuntimeMaxUselo stesso per il journal nella RAM sotto /run
MaxRetentionSecetà massima delle voci, indipendentemente dalla dimensione

La /etc/systemd/journald.conf fornita dalla distribuzione elenca tutte le chiavi come righe commentate con i rispettivi valori predefiniti, ed è quindi la fonte più affidabile per sapere che cosa vale in questo momento sul tuo sistema. Dopo ogni modifica serve systemctl restart systemd-journald, poi journalctl --disk-usage mostra il risultato.

Per l'intervento immediato su un disco pieno vale un ordine su cui in molti inciampano: le opzioni di pulizia toccano esclusivamente i file di journal già chiusi, mai quello attivo in quel momento. Senza una rotazione preventiva sembra non succedere nulla, e l'output recita più o meno Vacuuming done, freed 0B of archived journals.

journalctl --rotate
journalctl --vacuum-time=7d

Di più su questo tema, insieme agli altri divoratori di spazio, lo trovi nell'articolo Disco pieno su Linux.

Un secondo motivo per cui mancano delle righe è il limitatore di frequenza integrato, governato da RateLimitIntervalSec e RateLimitBurst: se un servizio scrive moltissimi messaggi in poco tempo, journald scarta l'eccedenza e lo annota con una riga che contiene la parola Suppressed. Se un log presenta dei buchi anche se il servizio era dimostrabilmente in funzione, cerca prima di tutto questo:

journalctl -b --grep "Suppressed" --no-pager

Messaggi del kernel: journalctl -k e dmesg

-k mostra esclusivamente i messaggi del kernel e comprende già -b, limita quindi automaticamente l'output all'avvio in corso. Chi dopo un riavvio cerca la causa deve richiedere esplicitamente quello precedente:

journalctl -k -p err --no-pager
journalctl -k -b -1 --no-pager

La differenza rispetto a dmesg sta nel luogo di conservazione. dmesg legge il ring buffer del kernel: limitato, va in overflow, dopo un riavvio è vuoto. Il journal conserva gli stessi messaggi, a patto che sia persistente. Per un incidente di ieri journalctl -k è quindi l'unica fonte affidabile. Due note pratiche: dmesg -T converte in orari i secondi trascorsi dall'avvio e dopo lunghi periodi di uptime sbaglia leggermente, il journal riporta sempre l'ora vera. E kernel.dmesg_restrict vale 1 su tutte e quattro le distribuzioni, quindi una chiamata senza root fallisce con Operation not permitted.

Perché molti server non hanno più /var/log/syslog

Il journal non è un'aggiunta ai classici file di testo, ne è il sostituto. /var/log/syslog e /var/log/auth.log non nascono da systemd, ma da un servizio syslog aggiuntivo, di solito rsyslog. Quello è un pacchetto a sé e nelle installazioni minime di Debian 12 e Debian 13 non fa più parte della dotazione. Sulle immagini server di Ubuntu 22.04 e 24.04 invece è presente.

ls -l /var/log/syslog /var/log/auth.log
systemctl status rsyslog --no-pager

Se non è installato nessun servizio syslog, il secondo comando risponde con Unit rsyslog.service could not be found. Questo spiega in un colpo solo tre osservazioni: le guide con tail -f /var/log/syslog falliscono con tail: cannot open '/var/log/syslog' for reading: No such file or directory, la ricerca dei tentativi di accesso in /var/log/auth.log non porta a nulla, e fail2ban deve prendere i suoi eventi dal journal. Come si imposta lo trovi nell'articolo configurare fail2ban.

Installare rsyslog a posteriori solo perché si è abituati a quei file conviene di rado: salveresti tutto due volte e ti servirebbe in più una regola logrotate funzionante. Ha senso quando i log devono confluire in un sistema centralizzato.

Schemi di ricerca pronti per l'emergenza

Un servizio è morto oppure si riavvia di continuo

systemctl list-units --type=service --state=failed --no-pager
journalctl -b -p err --no-pager
journalctl -b --grep "Main process exited|Failed with result|Start request repeated" --no-pager

La terza riga trova i messaggi con cui systemd segnala i crash e il suo freno agli avvii ripetuti. Se un core dump diventa interessante, è questo file a chiarire per primo chi se ne occupa:

cat /proc/sys/kernel/core_pattern

Se lì compare una chiamata a systemd-coredump, allora coredumpctl list elenca i dump presenti. Se compare qualcos'altro o solo core, se ne occupa un altro handler e coredumpctl resta vuoto.

Memoria esaurita

journalctl -k -b --grep "Out of memory|oom-kill" --no-pager
journalctl --since "-7d" --grep "Out of memory|oom-kill" --no-pager
journalctl -u systemd-oomd --since "-7d" --no-pager

Il secondo comando rinuncia di proposito a -k e cerca quindi anche attraverso avvii diversi. Il terzo vale per Ubuntu 22.04 e 24.04, dove systemd-oomd gira di serie e termina interi control group prima che intervenga il kernel; su Debian questo servizio non fa parte della dotazione standard. Come si distinguono i messaggi lo trovi nell'articolo Configurare lo swap ed evitare gli out of memory.

Accessi falliti

journalctl -u ssh --since "-24h" --grep "Failed password|Invalid user" --no-pager

Più interessante delle singole righe è la distribuzione. La riga seguente conta gli indirizzi di origine e li ordina in modo decrescente:

journalctl -u ssh --since "-24h" -g "Failed password" -o cat --no-pager | awk '{print $(NF-3)}' | sort | uniq -c | sort -rn | head

Il trucco sta nel contare dalla fine: il messaggio termina sempre con from INDIRIZZO port NUMERO ssh2, quindi il quartultimo campo è l'indirizzo, indipendentemente dal fatto che davanti ci fosse un nome utente valido o inventato e che si tratti di IPv4 o IPv6. Qui -o cat è obbligatorio, perché altrimenti timestamp e mittente spostano il conteggio dei campi. La controprova per gli accessi riusciti:

journalctl -u ssh --since "-7d" -g "Accepted (publickey|password)" -o cat --no-pager

Che cosa è successo alle 03:14, e che cosa c'era prima?

journalctl --since "2026-09-02 03:10" --until "2026-09-02 03:20" -o short-iso --no-pager
journalctl -b -1 -n 100 --no-pager
journalctl _PID=1234 --since "-1h" --no-pager

Il secondo comando mostra le ultime cento righe prima della fine precedente. Uno spegnimento ordinato lo riconosci dal fatto che lì systemd termina i servizi uno dopo l'altro. Se l'output si interrompe nel bel mezzo del normale funzionamento, si è trattato di un crash, di un reset forzato o di un'interruzione di corrente. Per il terzo comando vale questo: i numeri di processo vengono riutilizzati, senza una finestra temporale rischi di mescolare due programmi diversi in un unico output.

Errori frequenti e soluzioni

No journal files were found.: non ci sono file di journal leggibili. O systemd-journald non è in esecuzione, oppure come utente normale non hai accesso. Prima verifica con systemctl is-active systemd-journald, poi ripeti come root.

-- No entries --: il filtro non ha trovato niente. Non è un messaggio di errore, è una risposta corretta a una domanda forse sbagliata. Le tre cause più frequenti: un nome di unit che è solo un nome alternativo, una finestra temporale troppo stretta, e un -k anche se il messaggio cercato non veniva affatto dal kernel.

Hint: You are currently not seeing messages from other users and the system.: stai leggendo come utente normale. Fatti aggiungere al gruppo adm ed esegui un nuovo accesso, oppure lavora direttamente con sudo.

No journal boot entry found for the specified boot (-1) oppure No journal boot entry found from the specified boot offset (-1): nel journal non c'è nessun avvio precedente. È la norma finché il journal resta soltanto nella RAM.

Failed to add match: l'espressione non è un filtro di campo valido. I nomi dei campi sono in maiuscolo e il confronto avviene sul valore completo. Per le corrispondenze parziali nel testo del messaggio serve --grep.

Unknown key name 'SystemMaxUsage' in section 'Journal', ignoring: un errore di battitura nel file aggiuntivo. systemd salta la riga e prosegue con l'impostazione predefinita. Lo trovi con journalctl -u systemd-journald -b.

Vacuuming done, freed 0B of archived journals: non c'era nulla di archiviato da cancellare, perché lo spazio è occupato dal file attivo. Prima journalctl --rotate, poi ripeti la pulizia.

Operation not permitted con dmesg: kernel.dmesg_restrict vale 1. Ripeti come root oppure ripiega su journalctl -k.

File /var/log/journal/.../system.journal corrupted or uncleanly shut down, renaming and replacing.: il server si è spento di colpo mentre un file di journal era aperto. journald aggiunge una tilde al vecchio nome e comincia un file nuovo. Lo stato di tutti i file lo verifichi con journalctl --verify, che per ogni file stampa una riga con PASS; le anomalie segnalate riguardano di norma proprio i vecchi file con la tilde.

Differenze tra Debian 13, Debian 12, Ubuntu 24.04 e 22.04

  • Debian 13 (trixie): systemd 257. OpenSSH 10.0, gli accessi stanno sotto l'identificatore sshd-session. rsyslog assente nelle installazioni minime, in quel caso manca /var/log/syslog. systemd-oomd non fa parte della dotazione standard.
  • Debian 12 (bookworm): systemd 252. OpenSSH 9.2, tutto sotto sshd. rsyslog presente a seconda della variante di installazione, quindi /var/log/syslog non è garantito. systemd-oomd non fa parte della dotazione standard.
  • Ubuntu 24.04 LTS: systemd 255. OpenSSH 9.6, tutto sotto sshd. rsyslog presente. systemd-oomd attivo di serie. SSH parte tramite socket activation, quindi controlla nel journal il nome effettivo della unit.
  • Ubuntu 22.04 LTS: systemd 249. OpenSSH 8.9, tutto sotto sshd. rsyslog presente. systemd-oomd attivo di serie. È la più vecchia delle quattro versioni di systemd, lì mancano alcuni formati di output più recenti.

Su tutti e quattro i sistemi l'essenziale resta uguale: stessi filtri, stesse priorità, stesso file di configurazione e stessa regola, cioè che a decidere la durata è /var/log/journal.


L'ordine che nella pratica quotidiana funziona: prima la finestra temporale, poi la unit, poi la priorità, e alla fine uno schema di ricerca. Chi procede così, per la maggior parte dei guasti non arriva nemmeno a tre comandi. E chi una volta si assicura che il journal sopravviva ai riavvii e abbia comunque un limite massimo, può ancora rispondere alla domanda sul perché quando il server è già tornato in funzione da un pezzo.

Domande frequenti

Come restringo il journal al periodo del guasto?
Prima la finestra temporale, solo dopo il nome del servizio e la priorità. journalctl --since "-30min" ti dà l'ultima mezz'ora, journalctl --since "2026-09-02 03:10" --until "2026-09-02 03:20" un intervallo fisso, e le forme brevi si chiamano -S e -U. Fai attenzione al fuso: journalctl lavora nell'ora locale del server, mentre le applicazioni scrivono spesso i log in UTC. Se infili senza controllare un timestamp preso da un log applicativo, d'estate finisci per cercare due ore accanto all'evento. Se torna -- No entries --, allarga la finestra a un'ora come prova, prima di dubitare dei filtri.
Perché journalctl -u mysql non restituisce nessuna riga anche se il database scrive i log?
Perché -u confronta per uguaglianza e non per somiglianza. Su un sistema Debian con MariaDB, mysql.service è soltanto un nome alternativo di mariadb.service, ma il journal salva le sue voci sotto il nome vero. Per questo ottieni -- No entries -- e nessun messaggio di errore, cioè una risposta sbagliata che non sembra affatto un errore. Il nome vero lo ricavi con journalctl -F _SYSTEMD_UNIT | sort | grep -i sql. Puoi anche disinnescare il problema con i pattern, perché -u li accetta: journalctl -u "mysql*" -u "mariadb*" -n 60 --no-pager.
Perché su Debian 13 gli accessi SSH non compaiono sotto journalctl -t sshd?
Dalla versione 9.8 OpenSSH sposta le sessioni in un processo separato, sshd-session. Su Debian 13 (OpenSSH 10.0) sotto -t sshd resta quindi solo l'informazione che il servizio è in ascolto, mentre ogni accesso finisce sotto -t sshd-session. Debian 12, Ubuntu 24.04 e Ubuntu 22.04 non conoscono questa suddivisione. Chi su Debian 13 filtra solo -t sshd crede tranquillo un server su cui in quel momento viene registrato ogni singolo tentativo. La strada che passa per la unit è più robusta, perché i processi figli appartengono alla stessa: journalctl -u ssh --since "-24h".
Perché -p err non mostra gli errori del servizio che ho scritto io?
Per impostazione predefinita, quello che un servizio scrive sullo standard output finisce nel journal come info, anche se stava sullo standard error. Un programma che stampa un'eccezione con tanto di stacktrace appare così come un innocuo messaggio di esercizio, e -p err lo nasconde. Un livello adeguato lo ottengono solo i programmi che scrivono direttamente sull'interfaccia del journal oppure antepongono alle proprie righe un prefisso syslog. Per i servizi scritti da te conviene quindi filtrare per unit e per testo, mentre per i servizi di sistema e per il kernel -p è invece del tutto utilizzabile.
Come faccio in modo che il journal sopravviva a un riavvio?
Con l'impostazione predefinita Storage=auto lo decide una sola directory: se /var/log/journal esiste, tutto viene conservato. Se non esiste, il journal sta nella RAM sotto /run/log/journal e dopo il riavvio successivo è sparito. Crea un file dedicato sotto /etc/systemd/journald.conf.d/, imposta lì Storage=persistent insieme a un limite come SystemMaxUse=500M e MaxRetentionSec=1month, riavvia il servizio con systemctl restart systemd-journald e recupera con journalctl --flush quello che si trova ancora in /run. La prova è un riavvio vero: dopo, journalctl --list-boots deve mostrare almeno due righe.
Che cosa significa "No journal boot entry found for the specified boot (-1)"?
Nel journal non c'è nessun avvio precedente. Su Ubuntu 24.04 la stessa cosa suona "No journal boot entry found from the specified boot offset (-1)". Non è un difetto, è l'avviso che lì non c'è niente da recuperare, ed è la norma finché il journal resta soltanto nella RAM. Se anche journalctl --list-boots mostra una riga sola, probabilmente il journal non viene conservato in modo permanente. Chi in futuro vuole analizzare l'avvio precedente deve passare prima a Storage=persistent.
Perché journalctl --vacuum-time non libera spazio?
Le opzioni di pulizia toccano esclusivamente i file di journal già chiusi, mai quello attivo in quel momento. Senza una rotazione preventiva sembra quindi non succedere nulla, e l'output recita più o meno "Vacuuming done, freed 0B of archived journals". L'ordine giusto è prima journalctl --rotate, poi journalctl --vacuum-time=7d. Tieni presente che la cancellazione è irreversibile, comprese le prove che stai cercando proprio in quel momento.
Perché sul mio server Debian non c'è /var/log/syslog?
Perché quel file non nasce da systemd, ma da un servizio syslog aggiuntivo, di solito rsyslog. Quello è un pacchetto a sé e nelle installazioni minime di Debian 12 e Debian 13 non fa più parte della dotazione, mentre sulle immagini server di Ubuntu 22.04 e 24.04 è presente. Se manca, systemctl status rsyslog risponde con "Unit rsyslog.service could not be found." e tail -f /var/log/syslog fallisce con "tail: cannot open '/var/log/syslog' for reading: No such file or directory". I messaggi ci sono comunque, li leggi con journalctl, e anche fail2ban prende i suoi eventi dal journal.

journalctl systemd Linux Debian Ubuntu File di log Risoluzione dei problemi Amministrazione server