Guida

Log in Linux: journalctl, /var/log, rsyslog e logrotate

Aggiornato: · Skillaria.Top

Nelle distribuzioni Linux moderne i log li raccoglie journald e si leggono con journalctl: journalctl -u nginx mostra le voci di un solo servizio, -f il flusso in tempo reale, --since e -p filtrano per orario e gravità. I log testuali si trovano in /var/log, li scrive rsyslog o l'applicazione stessa, e logrotate comprime ed elimina periodicamente i file vecchi per evitare che il disco si riempia.

Quando un servizio cade di notte, la risposta quasi sempre è nei log: la questione è solo dove cercarli. Nelle distribuzioni moderne (Ubuntu, Debian, RHEL, Fedora, Arch) gli eventi vengono raccolti dal servizio journald e si leggono con il comando journalctl. Allo stesso tempo molti programmi scrivono normali file di testo in /var/log, e la loro dimensione è controllata da logrotate. Qui sotto vediamo come usare i log di journalctl in Linux nella pratica, dove si trovano gli altri registri e come non perdere le informazioni importanti durante la rotazione.

Dove si trovano i log in Linux

Le fonti sono tre, ed è utile tenerle a mente come una mappa:

  • journald — il registro binario di systemd. Riceve stdout e stderr di tutti i servizi, i messaggi del kernel e syslog. Viene salvato in /var/log/journal/ (in modo permanente) oppure in /run/log/journal/ (fino al riavvio).
  • /var/log — file di testo. Li scrive rsyslog (ad esempio /var/log/syslog, /var/log/auth.log) oppure le applicazioni stesse: nginx, PostgreSQL, MySQL.
  • Buffer circolare del kernel — messaggi di driver e hardware, visibili con dmesg o journalctl -k.
FileContenuto
/var/log/syslog (Debian/Ubuntu)registro generale di sistema
/var/log/messages (RHEL/Fedora)la stessa funzione nella famiglia Red Hat
/var/log/auth.log oppure /var/log/secureaccessi, sudo, SSH
/var/log/kern.logmessaggi del kernel
/var/log/dpkg.log, /var/log/apt/installazione dei pacchetti
/var/log/nginx/access.log ed error.log del web server
/var/log/wtmp, /var/log/btmpregistri binari degli accessi, letti con last e lastb

La maggior parte dei file in /var/log è accessibile solo a root o al gruppo adm, quindi spesso i comandi di lettura vanno lanciati con sudo.

journalctl: comandi di base

Senza argomenti journalctl mostra l'intero journal dalle voci più vecchie, tramite il paginatore less. Di rado serve così: di solito si restringe subito la selezione.

journalctl              # tutto il journal, dal più vecchio al più recente
journalctl -e           # apre direttamente alla fine
journalctl -n 50        # ultime 50 righe
journalctl -r           # in ordine inverso, le più recenti in alto
journalctl --no-pager   # senza less, comodo per script e grep

Dentro il paginatore funzionano i soliti tasti di less: / — cerca, G — vai alla fine, q — esci. Le righe lunghe vengono tagliate alla larghezza dello schermo; le frecce destra e sinistra le fanno scorrere.

Log di un singolo servizio: journalctl -u

Lo scenario più frequente è vedere cosa ha scritto una certa unit di systemd. Non serve cercare il file né usare grep:

$ sudo journalctl -u nginx -n 20
Oct 14 03:12:41 web1 systemd[1]: Starting nginx.service - A high performance web server...
Oct 14 03:12:41 web1 nginx[1834]: nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
Oct 14 03:12:41 web1 systemd[1]: nginx.service: Control process exited, code=exited, status=1/FAILURE
Oct 14 03:12:41 web1 systemd[1]: nginx.service: Failed with result 'exit-code'.

Il flag -u si può ripetere: journalctl -u nginx -u php8.2-fpm mostra i due servizi mescolati in ordine cronologico, utile quando l'errore nasce al confine tra i due. Per le unit utente (systemctl --user) usa journalctl --user -u nome.

Log in tempo reale: journalctl -f

sudo journalctl -u nginx -f

È l'equivalente di tail -f: il comando mostra le ultime 10 voci e resta in attesa di quelle nuove. È comodo tenerlo in un terminale separato mentre riavvii il servizio o riproduci un errore. Si esce con Ctrl+C.

Filtri per orario e per avvio

Se sai quando è avvenuto un guasto, limita la selezione con --since e --until. Accettano sia date precise sia valori relativi:

journalctl --since "2026-10-14 02:50" --until "2026-10-14 03:30"
journalctl --since "1 hour ago"
journalctl --since yesterday --until today
journalctl -u nginx --since "10 min ago"

Un altro filtro utile è per avvio del sistema. Se il server si è riavviato da solo, la causa va cercata alla fine della sessione precedente:

$ journalctl --list-boots
 -2 8f1c...  Sat 2026-10-12 09:01:12 UTC  Sun 2026-10-13 22:47:03 UTC
 -1 a7d2...  Sun 2026-10-13 22:48:30 UTC  Tue 2026-10-14 03:05:51 UTC
  0 c3e9...  Tue 2026-10-14 03:07:02 UTC  Tue 2026-10-14 09:15:40 UTC

$ journalctl -b -1 -e      # fine dell'avvio precedente
$ journalctl -b            # solo l'avvio corrente

L'elenco degli avvii è disponibile solo se il journal viene salvato su disco. Come attivarlo è spiegato più avanti, nella sezione sulla configurazione di journald.

Filtro per gravità: journalctl -p

Ogni voce ha una priorità syslog da 0 a 7. Il flag -p mostra il livello indicato e tutti quelli più gravi:

CodiceNomeQuando si usa
0emergil sistema è inutilizzabile
1alertserve un intervento immediato
2criterrore critico
3errerrore
4warningavviso
5noticeevento significativo ma normale
6infomessaggio informativo
7debugdebug
journalctl -p err -b              # tutti gli errori dall'inizio dell'avvio
journalctl -p warning..err -u ssh # intervallo di livelli per un solo servizio

Il comando journalctl -p err -b è un ottimo primo controllo dopo un riavvio o un aggiornamento: in pochi secondi mostra cosa non ha funzionato.

Ricerca e altri filtri

journald memorizza per ogni voce dei campi strutturati, e si può filtrare per essi senza grep:

journalctl _PID=1834                 # per numero di processo
journalctl _COMM=sshd                # per nome del programma
journalctl _UID=1000                 # per utente
journalctl /usr/sbin/sshd            # per percorso dell'eseguibile
journalctl -k                        # solo i messaggi del kernel (come dmesg)
journalctl -t CRON                   # per identificatore syslog
journalctl -g "Out of memory"        # ricerca nel testo, con espressione regolare

Il flag -g (--grep) è disponibile da systemd 237; sui sistemi più vecchi usa la pipeline classica journalctl --no-pager | grep .... I filtri su campi diversi si combinano con un «E» logico, quindi journalctl -u nginx -p err --since today restituisce solo gli errori di nginx di oggi.

Formati di output

Il flag -o cambia il formato. Le varianti più utili:

  • -o short-iso — data in formato ISO 8601, comoda per confrontarla con i log dell'applicazione.
  • -o verbose — tutti i campi della voce, inclusi _SYSTEMD_UNIT, _PID, _BOOT_ID.
  • -o json oppure json-pretty — per l'elaborazione con script o jq.
  • -o cat — solo il testo del messaggio, senza data e host.
journalctl -u myapp -o json --since today | jq -r '.MESSAGE'

Configurare journald: conservazione e dimensioni

Le impostazioni si trovano in /etc/systemd/journald.conf (le modifiche conviene metterle in /etc/systemd/journald.conf.d/*.conf). Il parametro principale è Storage:

  • persistent — il journal viene scritto su disco in /var/log/journal e sopravvive al riavvio.
  • volatile — solo in memoria, in /run/log/journal.
  • auto (predefinito) — su disco se esiste la directory /var/log/journal.

Su alcune immagini minime la directory non esiste e, dopo un riavvio, la cronologia scompare. Per attivare la conservazione permanente:

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

Per evitare che il journal occupi tutto il disco, imposta dei limiti:

# /etc/systemd/journald.conf.d/size.conf
[Journal]
Storage=persistent
SystemMaxUse=500M
MaxRetentionSec=1month

Di default SystemMaxUse è il 10% della dimensione del file system, ma non più di 4 GB.

Come pulire il journal di journalctl

$ journalctl --disk-usage
Archived and active journals take up 1.8G in the file system.

sudo journalctl --vacuum-size=300M   # tenere al massimo 300 MB
sudo journalctl --vacuum-time=2weeks # eliminare le voci più vecchie di due settimane
sudo journalctl --rotate             # chiudere i file attivi, così possono essere eliminati anch'essi

Non conviene cancellare i file di /var/log/journal con rm: vacuum fa lo stesso in modo ordinato e non tocca il file attivo.

rsyslog: i classici log di testo

rsyslog è il demone che riceve i messaggi syslog (anche quelli inoltrati da journald) e li distribuisce nei file secondo delle regole. La configurazione si trova in /etc/rsyslog.conf e /etc/rsyslog.d/*.conf. Una regola è composta da un selettore sorgente.livello e da un'azione:

# /etc/rsyslog.d/50-default.conf (estratto)
auth,authpriv.*        /var/log/auth.log
*.*;auth,authpriv.none -/var/log/syslog
kern.*                 -/var/log/kern.log

Il trattino davanti al percorso indica una scrittura senza sincronizzazione su disco dopo ogni riga: è più veloce, ma in caso di guasto le ultime righe possono andare perse. Dopo aver modificato la configurazione, controlla la sintassi e riavvia il servizio:

sudo rsyslogd -N1
sudo systemctl restart rsyslog

La funzione principale per cui si tiene rsyslog accanto a journald è l'inoltro dei log a un server centrale. Una riga basta per inviare tutto via TCP:

# /etc/rsyslog.d/90-remote.conf
*.* @@logs.example.com:514

Un solo carattere @ indica UDP, due @@ indicano TCP. Se il server dovesse guastarsi del tutto, una copia dei log resta su un'altra macchina. Per scrivere un proprio messaggio nel registro di sistema da uno script, usa logger:

logger -t backup -p user.err "Backup del database non riuscito"
journalctl -t backup -n 5

logrotate: rotazione dei log

I log di testo crescono all'infinito finché qualcuno non li tronca. Se ne occupa logrotate: una volta al giorno (tramite cron o il timer logrotate.timer) rinomina il file corrente, comprime quelli vecchi ed elimina i più datati. Le impostazioni generali si trovano in /etc/logrotate.conf, le regole per i singoli programmi in /etc/logrotate.d/.

# /etc/logrotate.d/myapp
/var/log/myapp/*.log {
    daily
    rotate 14
    compress
    delaycompress
    missingok
    notifempty
    create 0640 myapp adm
    postrotate
        systemctl reload myapp > /dev/null 2>&1 || true
    endscript
}
DirettivaSignificato
daily / weekly / size 100Mquando ruotare
rotate 14quante copie vecchie conservare
compress, delaycompresscomprimere con gzip, ma lasciare non compresso l'archivio più recente
missingok, notifemptynon segnalare un file mancante, non ruotare quelli vuoti
create 0640 user groupcon quali permessi creare il nuovo file
copytruncatecopiare il file e azzerarlo — per i programmi che non sanno riaprire il log
postrotate ... endscriptcomando eseguito dopo la rotazione, di solito un segnale all'applicazione perché riapra il file

Per verificare una regola senza modificare nulla, o per forzare la rotazione:

sudo logrotate -d /etc/logrotate.d/myapp   # prova a secco con dettagli di debug
sudo logrotate -f /etc/logrotate.d/myapp   # ruota subito

Errore tipico: dimenticare postrotate o copytruncate. In quel caso l'applicazione continua a scrivere nel file rinominato app.log.1 tramite il vecchio descrittore, mentre il nuovo app.log resta vuoto.

Lettura dei log di testo

Per i file in /var/log bastano le utility standard:

sudo tail -n 100 /var/log/syslog          # ultime righe
sudo tail -F /var/log/nginx/error.log     # seguire anche attraverso la rotazione
sudo less +G /var/log/auth.log            # aprire alla fine
sudo zgrep "Failed password" /var/log/auth.log.*.gz   # ricerca negli archivi compressi
sudo grep -c " 500 " /var/log/nginx/access.log        # quante risposte 500

Nota il tail -F con la maiuscola: a differenza di -f, riapre il file quando logrotate lo sostituisce.

Analisi passo passo di un guasto

Lo scenario «il servizio è caduto di notte» si analizza seguendo un ordine preciso:

  1. systemctl status myapp — stato attuale e ultime righe del log.
  2. journalctl -u myapp --since "03:00" --until "03:30" — cosa ha scritto il servizio nel momento della caduta.
  3. journalctl -p err -b — ci sono altri errori nel sistema nello stesso periodo?
  4. journalctl -k --since "03:00" -g "Out of memory|Killed process" — ha ucciso un processo l'OOM killer del kernel?
  5. I log dell'applicazione in /var/log/myapp/, comprese le copie .gz.
  6. Se il server si era riavviato — journalctl -b -1 -e.

Conclusioni

Per il lavoro quotidiano con i log in Linux bastano pochi comandi: journalctl -u per un servizio, -f per il flusso, --since e -p err per restringere la selezione, -b -1 per analizzare un riavvio. I log di testo stanno in /var/log, rsyslog li distribuisce e li inoltra, mentre logrotate e journalctl --vacuum-* impediscono che i log riempiano il disco. Il lavoro con journalctl, la rotazione e la diagnostica del carico è trattato in modo pratico nella lezione del corso Linux.

Domande frequenti

Perché journalctl mostra solo le voci dell'ultimo avvio?

Il journal è conservato in memoria (/run/log/journal). Crea la directory /var/log/journal oppure imposta Storage=persistent in journald.conf e riavvia systemd-journald.

Come far leggere il log di sistema a un utente normale senza sudo?

Aggiungilo al gruppo systemd-journal (oppure adm su Debian e Ubuntu): sudo usermod -aG systemd-journal nome, poi riaccedi.

Posso leggere il journal di un altro sistema, ad esempio da un disco collegato?

Sì, indica la directory del journal con il flag -D: journalctl -D /mnt/var/log/journal. Il flag --file legge un singolo file .journal.

Serve rsyslog se c'è già journald?

Non è obbligatorio. È utile se servono i file di testo per strumenti più vecchi oppure per inoltrare i log a un server centrale; su molte immagini minime non viene più installato.

Come esporto i log di un servizio in un file da mandare a un collega?

Esegui journalctl -u nome --since today --no-pager > servizio.log: si ottiene un normale file di testo.

Impara l’argomento in video

Questo argomento è trattato in modo approfondito, con pratica, nel corso «Linux: с нуля до уверенного администрирования».

Vai al corso