Una chiavetta USB non compare, un disco rallenta all'improvviso, un processo sparisce senza lasciare traccia: la spiegazione è spesso in una riga scritta dal kernel, e quella riga non è in nessun file di log dei programmi. Si legge con dmesg, il primo comando da provare quando qualcosa va storto "sotto" il sistema.
Cos'è
dmesg (display message, o diagnostic message) fa parte del pacchetto util-linux, come lscpu, lsblk e mount. Il kernel (vedi l'articolo su uname) scrive tutto quello che gli succede in un'area di memoria circolare, il kernel ring buffer: l'avvio, i dispositivi riconosciuti, i driver caricati, gli errori dei dischi e della rete. "Circolare" vuol dire che ha una dimensione fissa e, quando è piena, i messaggi più vecchi vengono sovrascritti da quelli nuovi. dmesg legge questo buffer e lo mostra.
Cosa fa
Mostra i messaggi del kernel con un tempo in secondi dall'avvio, e permette di filtrarli per gravità, di convertire i tempi in date leggibili, di seguirli in diretta, di ottenerli in JSON e di svuotare il buffer. È in sola lettura per i messaggi: non li modifica, a meno che tu non chieda di cancellarli.
Come si usa
$ dmesg [opzioni]Gli esempi dal "sandbox" sono output reali di una macchina virtuale di prova, con un kernel 6.18 e dmesg di util-linux 2.39; quelli di web01, il server degli articoli precedenti, sono illustrativi e servono a mostrare messaggi tipici. Righe lunghe sono state accorciate con cut, per entrare nella pagina.
Esempio 1: leggere i messaggi
$ dmesg | wc -l
374
$ dmesg | head -n 3 | cut -c1-70
[ 0.000000] Linux version 6.18.44-fc-v236 (builder@sandboxing) (gcc (GCC)
[ 0.000000] Command line: deferred_init=lazy dhash_entries=131072 ihash_en
[ 0.000000] BIOS-provided physical RAM map:
$ dmesg | tail -n 3
$ dmesg | lessOgni riga ha un numero tra parentesi quadre: sono i secondi trascorsi dall'avvio del kernel. Il tempo 0.000000 è l'inizio dell'avvio; più il numero è alto, più la riga è recente. Il buffer è lungo (qui 374 righe) ed è raro leggerlo tutto: si usa tail per gli ultimi messaggi, less per scorrerlo (vedi l'articolo su head e tail) o grep per cercare. Le prime righe (la versione del kernel e i parametri di avvio) si leggono anche con cat /proc/version e cat /proc/cmdline. Su alcune distribuzioni dmesg usa direttamente il pager quando l'output è lungo: si disattiva con -P.
Esempio 2: tempi leggibili
$ dmesg -T | tail -n 2
[Thu Nov 5 06:33:49 2026] prova articolo dmesg
[Thu Nov 5 06:33:51 2026] prova warn
$ dmesg -H | tail -n 2
[Nov 5 06:33] prova articolo dmesg
[ +1.998014] prova warn
$ dmesg --time-format=iso | tail -n 1
2026-11-05T06:33:51,285420+01:00 prova warn
$ dmesg -t | tail -n 1
prova warnDire "all'istante 2814,5" è poco utile: con -T (ctime) i secondi diventano una data e un'ora. Il kernel però conta i secondi dall'avvio e dmesg ricostruisce la data sottraendo il tempo trascorso dall'ora attuale: se il computer è stato sospeso (suspend), il risultato può essere sbagliato di qualche minuto o ora. Il manuale lo dice espressamente ("may be inaccurate"). Altre forme: -H (human) mostra un'ora generica e, per ogni riga, il tempo trascorso dalla precedente; --time-format=iso dà date in formato ISO, ordinabili e adatte agli script; -t toglie del tutto i tempi, per confrontare due output o passare il testo a un altro comando. Qui le righe finali sono due messaggi di prova che ho scritto io nel buffer (esempio 6).
Esempio 3: filtrare per gravità
$ dmesg -l err,warn -t
software IO TLB: No low mem
EXT4-fs (vda): warning: mounting unchecked fs, running e2fsck is recommended
$ dmesg -l warn+ -t | head -n 2 | cut -c1-60
software IO TLB: No low mem
EXT4-fs (vda): warning: mounting unchecked fs, running e2fsck is r
$ dmesg -x -t | sed -n 1,2p | cut -c1-60
kern :notice: [ 0.000000] Linux version 6.18.44-fc-v236 (builder@sandboxi
kern :info : [ 0.000000] Command line: deferred_init=lazy dhash_entries=
$ dmesg -f kern,daemon -t | wc -l
374I messaggi hanno un livello, dal più grave al meno grave: emerg (il sistema è inutilizzabile), alert, crit, err, warn, notice, info e debug. Con -l (level) si scelgono i livelli da mostrare: nell'esempio solo gli avvisi e gli errori (nel sandbox ce ne sono solo due, innocui). Il suffisso + include anche i livelli più gravi. Con -x (decode) ogni riga indica la facility (la provenienza: kern per il kernel, user per i programmi, daemon...) e il livello in forma leggibile. Con -f si filtra per facility. Per cercare problemi è il filtro più comodo: dmesg -l err,crit,alert,emerg.
Esempio 4: se non funziona senza sudo
$ dmesg
dmesg: read kernel buffer failed: Operation not permitted
$ sudo dmesg | tail -n 2
$ sysctl kernel.dmesg_restrict
kernel.dmesg_restrict = 1Su molte distribuzioni un utente normale non può leggere il buffer, e riceve Operation not permitted (nel sandbox ho riprodotto l'errore con un utente senza privilegi). Il motivo è il parametro kernel.dmesg_restrict: a 1 solo l'amministratore legge il buffer, perché i messaggi del kernel possono rivelare indirizzi di memoria e dettagli utili a un attaccante (vedi l'articolo su sysctl). La soluzione normale è usare sudo dmesg. Si potrebbe mettere il parametro a 0, ma è una scelta di sicurezza: su un server è meglio lasciarlo com'è. Su altre distribuzioni (o con valore 0) l'utente normale può leggere.
Esempio 5: cercare un problema
$ sudo dmesg -T | grep -i -E 'error|fail|oom|killed|i/o' | tail -n 5
[Wed Nov 4 03:12:41 2026] Out of memory: Killed process 4821 (php-fpm)
[Wed Nov 4 03:12:41 2026] oom_reaper: reaped process 4821 (php-fpm)
[Thu Nov 5 01:07:19 2026] EXT4-fs error (device sdb1): ext4_find_entry:1455
[Thu Nov 5 01:07:19 2026] blk_update_request: I/O error, dev sdb, sector 2048
[Thu Nov 5 05:58:03 2026] r8169 0000:03:00.0 eno1: Link is Down
$ dmesg | grep -i vda
$ dmesg -t | grep -i -m 2 vda | cut -c1-80
virtio_blk virtio1: [vda] 536870912 512-byte logical blocks (275 GB/256 GiB)
virtio_blk virtio1: [vda] new size: 536870912 512-byte logical blocks (275 GB/256 GiB)Le righe dell'OOM killer, degli errori di I/O e dell'interfaccia di rete (blocchi web01) sono illustrative, ma sono tra i messaggi più tipici. Out of memory: Killed process significa che la memoria è finita e il kernel ha eliminato un processo per salvare il sistema (vedi gli articoli su free e ps: è il motivo per cui un programma "muore da solo"). I/O error e EXT4-fs error sono segnali di un problema ai dischi o al file system (vedi lsblk e mount), da prendere sul serio. Link is Down riguarda un cavo o una scheda di rete (vedi ip). La seconda parte (con vda) è reale: mostra come cercare un dispositivo per nome; con -m 2 grep si ferma alla seconda riga trovata (vedi l'articolo su grep).
Esempio 6: seguire i messaggi in diretta
$ sudo dmesg -w
$ sudo dmesg -W -T
$ echo "prova articolo dmesg" | sudo tee /dev/kmsg
prova articolo dmesg
$ sudo dmesg -t | tail -n 1
prova articolo dmesgCon -w (follow) dmesg resta in attesa e stampa i nuovi messaggi appena arrivano, come tail -f; si ferma con Ctrl+C. Con -W (follow-new) parte senza mostrare quelli già presenti. È utile per vedere "in diretta" cosa dice il kernel mentre si inserisce una chiavetta, si collega un cavo o si prova un servizio. Nel sandbox ho provato entrambe le opzioni. Si può anche scrivere un messaggio nel buffer, per i test o per segnare un momento: basta scrivere nel file speciale /dev/kmsg (con tee e sudo, perché la redirezione > la fa la shell senza privilegi: vedi gli articoli su tee e sysctl). Un messaggio scritto così compare con facility user. Con -u si vedono solo i messaggi dei programmi, con -k solo quelli del kernel.
Esempio 7: svuotare il buffer
$ sudo dmesg -C
$ sudo dmesg -c > /tmp/dmesg-prima.txt
$ sudo dmesg | wc -l
0-C (clear) cancella il buffer; -c (read-clear) lo legge e poi lo cancella. Serve quando si vuole isolare un problema: si svuota, si ripete l'operazione che dà errore e si legge cosa è comparso. Ma attenzione: i messaggi cancellati sono persi (a meno che il sistema non li abbia già copiati in un file: vedi "Attenzione a"). Meglio salvarli prima, come nel secondo comando. Non ho eseguito queste due righe nel sandbox, per non perdere i dati di prova: l'effetto è quello descritto dal manuale.
Esempio 8: uso negli script
#!/bin/bash
# Segnala se il kernel ha registrato errori nel buffer dei messaggi
LIVELLI="emerg,alert,crit,err"
N=$(dmesg -t -l "$LIVELLI" 2>/dev/null | wc -l)
if [ "$N" -gt 0 ]; then
echo "Il kernel ha registrato $N messaggi di errore:" >&2
dmesg -t -l "$LIVELLI" | tail -n 5 >&2
exit 1
fi
echo "Nessun errore nel buffer del kernel"Lo script conta i messaggi dai livelli più gravi e, se ce ne sono, stampa gli ultimi cinque e termina con un errore (exit 1, per accorgersene da cron: vedi l'articolo su crontab). Si lancia con sudo (o dall'amministratore). L'ho provato nel sandbox: con il buffer pulito risponde "Nessun errore nel buffer del kernel"; dopo aver scritto un messaggio di livello err in /dev/kmsg, si è fermato con il codice 1 e con il messaggio. Con -J (JSON) dmesg produce anche un output strutturato, con livello, tempo e testo per ogni riga, da elaborare con jq.
Opzioni utili
dmesg: tutto il buffer;-T: date leggibili;-H: formato umano;--time-format=iso: date ISO;-t: senza tempi.-l livelli: filtra per livello (err,warn, owarn+per quel livello e i più gravi);-f facility: filtra per provenienza;-x: mostra facility e livello.-w: segue i messaggi in diretta;-W: come-w, ma solo i nuovi.-k: solo i messaggi del kernel;-u: solo quelli dei programmi.--since,--until: intervallo di tempo (con una data o un tempo relativo come-1h).-C: cancella il buffer;-c: legge e cancella;-J: JSON;-L: colori;-P: senza pager.journalctl -k: gli stessi messaggi dal journal;journalctl -k -b -1: quelli dell'avvio precedente.
Attenzione a
- Il buffer è circolare, e si perde al riavvio: su un sistema molto attivo, i messaggi vecchi vengono sovrascritti, e dopo un riavvio non ci sono più. Per l'avvio precedente serve il registro persistente:
journalctl -k -b -1(se il journal è salvato su disco: vedi l'articolo sujournalctl), oppure il file/var/log/kern.logdove c'èrsyslog. Nel sandbox non c'era nessuno dei due. - Gli orari di
-Tnon sono sicuri: dopo una sospensione, un'ibernazione o una correzione dell'ora di sistema possono essere sbagliati. Per gli orari esatti usajournalctl -k, che registra l'ora vera al momento del messaggio. - Non è necessariamente un problema, solo perché c'è scritto
errorofail: nel buffer ci sono avvisi innocui (come i due del sandbox). Valuta il contesto e la frequenza: una riga isolata all'avvio non è lo stesso di una che si ripete ogni secondo. - Con
sudosi può leggere, ma anche cancellare:dmesg -ce-Celiminano prove utili. Per un'indagine, salva sempre l'output prima:sudo dmesg -T > dmesg-$(date +%F).txt. - Un utente normale spesso non ha il permesso: vedi l'esempio 4; non rendere il buffer pubblico (
kernel.dmesg_restrict=0) solo per comodità. - Nei container si vede il buffer della macchina ospite, se lo si può leggere; spesso è bloccato o vuoto. Il comando serve davvero sulla macchina fisica o virtuale, non dentro un container.
- I messaggi dipendono dal kernel e dai driver: le righe d'esempio (OOM,
I/O error,Link is Down) cambiano nella forma da una versione all'altra, e da un driver all'altro: cerca le parole chiave, non il testo esatto.
Riepilogo
| Comando | Cosa fa |
|---|---|
sudo dmesg | Mostra i messaggi del kernel |
sudo dmesg | tail -n 20 | Mostra gli ultimi messaggi |
sudo dmesg -T | Con data e ora leggibili |
sudo dmesg -H | Formato "umano", con i tempi relativi |
sudo dmesg -l err,crit,alert,emerg | Solo errori gravi |
sudo dmesg -x | Mostra provenienza e livello |
sudo dmesg | grep -i usb | Cerca i messaggi di un dispositivo |
sudo dmesg -w | Segue i nuovi messaggi in diretta |
sudo dmesg -T > file.txt | Salva i messaggi in un file |
sudo dmesg -c | Legge e svuota il buffer |
journalctl -k -b -1 | Messaggi del kernel dell'avvio precedente |
Nel prossimo articolo: lsmod, per vedere i moduli caricati nel kernel, cioè i driver in uso.