Quale modello è questo server? Qual è il suo numero di serie, per la garanzia? Quanti banchi di memoria ha, quanti sono occupati e di che tipo? A quale versione di BIOS è fermo? Sono domande a cui lshw risponde in parte; la fonte originale di queste informazioni è il firmware della scheda madre, e dmidecode lo legge direttamente.
Cos'è
Ogni scheda madre porta nel suo firmware (il BIOS o l'UEFI) una tabella che descrive la macchina: costruttore, modello, numeri di serie, versione del firmware, processore, banchi di memoria, slot. Il formato si chiama SMBIOS (System Management BIOS), o anche DMI (Desktop Management Interface, il nome più vecchio, da cui dmidecode). Il programma dmidecode (su Debian e Ubuntu: sudo apt install dmidecode, vedi l'articolo su apt) legge questa tabella e la decodifica in testo leggibile.
Cosa fa
Mostra le informazioni che il costruttore ha scritto nel firmware: un blocco per ogni "voce" della tabella, numerata per tipo (tipo 0 = BIOS, 1 = sistema, 2 = scheda madre, 3 = telaio, 4 = processore, 17 = banco di memoria, e così via). Si può chiedere un solo tipo, una sola stringa (come il numero di serie), oppure salvare la tabella grezza in un file. Non modifica niente: legge soltanto.
Come si usa
$ sudo dmidecode [opzioni]Una precisazione importante sulle prove. La macchina virtuale che uso per verificare i comandi non ha le tabelle DMI (non esiste né /sys/firmware/dmi né /dev/mem), perciò dmidecode non ha niente da leggere. Per mostrare un output vero ho costruito io una tabella SMBIOS inventata (un finto server "ExampleServer T1" di "Example Systems", con quattro slot di memoria e due moduli da 16 GB) e l'ho data in pasto al dmidecode vero con l'opzione --from-dump. Quindi: il formato degli output è quello vero del programma (versione 3.5), mentre i valori (modello, serie, memoria) sono inventati e sul tuo server saranno diversi. Con --from-dump nelle prime righe compaiono Reading SMBIOS/DMI data from file dump.bin.; su una macchina reale al suo posto c'è una riga che dice da dove ha letto i dati.
Esempio 1: il primo sguardo
$ sudo dmidecode | head -n 29
# dmidecode 3.5
Reading SMBIOS/DMI data from file dump.bin.
SMBIOS 3.4.0 present.
Handle 0x0000, DMI type 0, 24 bytes
BIOS Information
Vendor: Example Systems
Version: 2.14.1
Release Date: 03/12/2024
Address: 0xE0000
Runtime Size: 128 kB
ROM Size: 4 MB
Characteristics:
BIOS is upgradeable
BIOS shadowing is allowed
Boot from CD is supported
ACPI is supported
Targeted content distribution is supported
UEFI is supported
BIOS Revision: 2.4
Handle 0x0100, DMI type 1, 27 bytes
System Information
Manufacturer: Example Systems
Product Name: ExampleServer T1
Version: 1.0
Serial Number: EX0123456
UUID: 4c4c4544-0042-3510-8051-b8c04f4b5a33
Wake-up Type: Power SwitchL'output completo è lungo, perciò si guarda a pezzi (head, less: vedi gli articoli relativi). Ogni blocco comincia con una riga Handle 0x..., DMI type N, M bytes: l'handle è un identificativo interno, type è il tipo di voce (0 = BIOS, 1 = sistema...) e bytes la dimensione della voce. Poi viene il nome della voce (BIOS Information, System Information) e i campi indentati. La riga SMBIOS 3.4.0 present. dice la versione del formato. Le informazioni da guardare per prime: Vendor e Version del BIOS (con la data), e Manufacturer, Product Name e Serial Number del sistema. Nel testo dell'output reale i rientri sono tabulazioni; qui li ho resi con spazi.
Esempio 2: scegliere un tipo di voce
$ sudo dmidecode -t system
$ sudo dmidecode -t bios -t baseboard
$ sudo dmidecode -t 17
$ sudo dmidecode -t 1,2
$ sudo dmidecode -t
dmidecode: option requires an argument -- 't'
Type number or keyword expected
Valid type keywords are:
bios
system
baseboard
chassis
processor
memory
cache
connector
slot
$ sudo dmidecode -t bogus
Invalid type keyword: bogus
Valid type keywords are:
bios
...Con -t (type) si sceglie la voce da mostrare, con una parola chiave oppure con il numero (i numeri si separano con una virgola, come in -t 1,2). Le parole chiave sono nove (l'elenco sopra è quello vero, stampato dal programma senza argomento): bios, system, baseboard (la scheda madre), chassis (il telaio), processor, memory, cache, connector (le porte) e slot (gli slot di espansione). memory raggruppa più tipi (tra cui il 16, l'insieme dei banchi, e il 17, ogni singolo banco). Un tipo scritto male dà il messaggio Invalid type keyword e l'elenco delle parole valide.
Esempio 3: la memoria, banco per banco
$ sudo dmidecode -t memory -q | grep -E 'Locator|Size|Type:|Speed|Part'
Error Correction Type: Multi-bit ECC
Size: 16 GB
Locator: DIMM_A1
Bank Locator: BANK 0
Type: DDR4
Speed: 3200 MT/s
Part Number: EM16G3200
Size: No Module Installed
Locator: DIMM_A2
Bank Locator: BANK 0
Type: Unknown
Size: 16 GB
Locator: DIMM_B1
Bank Locator: BANK 1
Type: DDR4
Speed: 3200 MT/s
Part Number: EM16G3200
Size: No Module Installed
Locator: DIMM_B2
Bank Locator: BANK 1
Type: Unknown
$ sudo dmidecode -t 16 -q | grep -E 'Maximum|Devices|Correction'
Error Correction Type: Multi-bit ECC
Maximum Capacity: 64 GB
Number Of Devices: 4È l'uso più frequente: capire cosa c'è nei banchi di memoria prima di comprare altra RAM. Ogni Memory Device è uno slot: se c'è un modulo mostra Size, Type (DDR4), Speed e il codice del modello (Part Number); se è vuoto dice No Module Installed. Locator è il nome stampato sulla scheda (DIMM_A1), utile per sapere dove infilare il modulo nuovo. Il tipo 16 (Physical Memory Array) dice la capacità massima della scheda (Maximum Capacity), il numero totale di slot e se la memoria è con correzione degli errori (ECC). Nell'esempio: 4 slot, 2 occupati da 16 GB (32 GB in tutto), massimo 64 GB. Con -q (quiet) si tolgono le righe di intestazione e gli Handle. Confronta il totale con free (vedi l'articolo relativo): quello di free è un po' inferiore, perché una parte è riservata dal sistema.
Esempio 4: una sola informazione, per gli script
$ sudo dmidecode -s system-serial-number
EX0123456
$ sudo dmidecode -s system-product-name
ExampleServer T1
$ sudo dmidecode -s bios-version
2.14.1
$ sudo dmidecode -s bios-release-date
03/12/2024
$ sudo dmidecode -s chassis-type
Tower
$ sudo dmidecode -s processor-version
Intel(R) Xeon(R) E-2314 CPU @ 2.80GHz
$ sudo dmidecode -s
dmidecode: option requires an argument -- 's'
String keyword expected
Valid string keywords are:
bios-vendor
bios-version
...
processor-frequency
cache
connector
slotCon -s (string) si ottiene solo il valore, senza intestazioni: è la forma da usare negli script. Le parole chiave valide sono un elenco fisso (bios-vendor, bios-version, system-manufacturer, system-product-name, system-serial-number, system-uuid, baseboard-*, chassis-*, processor-*): sudo dmidecode -s senza argomento le stampa tutte (l'elenco è quello vero). Un nome sbagliato dà Invalid string keyword e l'elenco. Nel sandbox le ho provate sulla tabella inventata; con una macchina vera i valori sono quelli del tuo hardware. Il numero di serie del sistema (system-serial-number) è quello da dare all'assistenza del costruttore, e il system-uuid identifica la macchina.
Esempio 5: quando non funziona
$ dmidecode -s system-serial-number
/sys/firmware/dmi/tables/smbios_entry_point: Permission denied
Scanning /dev/mem for entry point.
/dev/mem: Permission denied
$ sudo dmidecode -s system-serial-number
Can't read memory from /dev/mem
$ cat /sys/class/dmi/id/product_name
ExampleServer T1
$ cat /sys/class/dmi/id/product_serial
cat: /sys/class/dmi/id/product_serial: Permission deniedSono gli errori da riconoscere. Senza privilegi si ottiene un Permission denied (le prime quattro righe sono un esempio illustrativo del messaggio che si vede su un sistema normale, che ora non posso riprodurre). Sulle macchine senza tabelle DMI, come il mio sandbox, dmidecode prova a cercare nella memoria (Scanning /dev/mem for entry point.) e termina con Can't read memory from /dev/mem: l'ho visto davvero, e vale per molte macchine virtuali, per i container e per alcuni dispositivi con processore ARM (come il Raspberry Pi), che non hanno un BIOS con SMBIOS. Una strada senza dmidecode è la cartella /sys/class/dmi/id/, dove il kernel espone gli stessi dati come file: product_name, sys_vendor e bios_version sono leggibili da tutti, mentre quelli riservati (product_serial, product_uuid) solo dall'amministratore. Gli ultimi quattro comandi sono illustrativi: il sandbox non ha quella cartella.
Esempio 6: i dati grezzi e il salvataggio
$ sudo dmidecode --dump-bin /tmp/web01-dmi.bin
$ dmidecode --from-dump /tmp/web01-dmi.bin -t system
$ sudo dmidecode -u -t 1 -q | head -n 8
Handle 0x0100, DMI type 1, 27 bytes
Header and Data:
01 1B 00 01 01 02 03 04 44 45 4C 4C 42 00 10 35
80 51 B8 C0 4F 4B 5A 33 06 05 06
Strings:
45 78 61 6D 70 6C 65 20 53 79 73 74 65 6D 73 00
Example Systems
45 78 61 6D 70 6C 65 53 65 72 76 65 72 20 54 31
$ sudo dmidecode -H 0x0100 -qCon --dump-bin FILE la tabella viene salvata in un file binario: è comodo per far analizzare i dati a qualcun altro, o per archiviare l'inventario di una macchina prima di intervenire. Con --from-dump FILE si rilegge il file con dmidecode anche su un altro computer, senza privilegi: è proprio quello che ho fatto per questo articolo (il file lo avevo costruito io, perché sul sandbox il comando --dump-bin non ha nulla da salvare: quella riga è illustrativa). Le due opzioni non si combinano: dmidecode risponde Options --from-dump and --dump-bin are mutually exclusive (verificato). Con -u (dump) le voci non sono decodificate ma mostrate in esadecimale, come nell'esempio (reale, sulla tabella inventata); con -H si chiede una voce per il suo Handle.
Esempio 7: uso negli script
#!/bin/bash
# Riepilogo dei banchi di memoria dai dati DMI (da eseguire come root)
if [ "$(id -u)" -ne 0 ]; then
echo "Serve l'amministratore: usa sudo" >&2
exit 1
fi
dmidecode -t memory | awk '
/^Memory Device/ { slot++ }
/^\tSize: [0-9]/ {
pieni++
if ($3 == "GB") mb += $2 * 1024; else mb += $2
}
END { printf "Banchi: %d, popolati: %d, totale: %d GB\n", slot, pieni, mb / 1024 }'Lo script conta i banchi di memoria, quelli popolati e la capacità totale, leggendo l'output di dmidecode -t memory con awk (vedi l'articolo relativo). Le righe Size: sono precedute da una tabulazione (\t nello script) e a volte l'unità è MB invece di GB: il codice gestisce entrambe, e un banco vuoto (No Module Installed) non viene contato perché dopo Size: non c'è una cifra. L'ho provato sui dati inventati, con un piccolo programma che sostituisce dmidecode e legge il file: ha risposto Banchi: 4, popolati: 2, totale: 32 GB; lanciato da un utente senza privilegi si ferma con il messaggio e il codice 1.
Opzioni utili
dmidecode: tutta la tabella;-t tipo: un tipo di voce (parola chiave o numero, ripetibile);-s parola: una sola stringa;-q: output ridotto.-H handle: una voce per identificativo;-u: voci non decodificate, in esadecimale.--dump-bin file: salva la tabella;--from-dump file: la rilegge (anche su un'altra macchina).--no-sysfs: non usa i file di/sys;-d file: legge la memoria da un file diverso da/dev/mem./sys/class/dmi/id/: i dati principali come file semplici.lshw,lscpu,free,lsblk,lspci: le altre viste sull'hardware;hostnamectl: modello e tipo di macchina.
Attenzione a
- Serve
sudo: le tabelle e i dati sensibili (numero di serie, UUID) sono accessibili solo all'amministratore. Senza privilegi,dmidecodefallisce conPermission denied. - I dati sono quelli scritti dal costruttore, non misurati:
dmidecodenon verifica nulla. Se il produttore ha lasciato campi segnaposto (To Be Filled By O.E.M.,Default string,Not Specified) li vedi tali e quali, e capita su schede economiche o assemblate. Anche la velocità della memoria è quella dichiarata dal modulo, non quella a cui lavora (per quella, ci sonoConfigured Memory Speedolshw). - Nelle macchine virtuali i dati sono finti o assenti: l'ambiente di virtualizzazione scrive una sua tabella (o nessuna): il modello può essere
Standard PCo il nome dell'ambiente, e i banchi di memoria sono un solo blocco virtuale. Come ho visto, in alcune macchine non c'è proprio nulla da leggere. - Non c'è un verbo "scrivi":
dmidecodeè solo di lettura. Alcuni costruttori offrono strumenti propri per cambiare certi campi (il numero di serie, il tag di inventario), ma passano dal firmware e non da qui. - I dati sono riservati: seriali, UUID e tag di inventario identificano una macchina precisa. Non incollarli in pubblico, nei forum o nelle segnalazioni, a meno di toglierli (vedi
lshw -sanitize, che fa il lavoro perlshw). - Un vecchio firmware può dare informazioni sbagliate: errori nella tabella (capacità massima, numero di slot) si verificano su firmware vecchi o difettosi. Quando i numeri non tornano, controlla anche il manuale della scheda madre e confronta con
freeelshw. - Attenzione ai comandi che modificano il firmware: aggiornare il BIOS (con gli strumenti del costruttore, o con
fwupd) è un'altra operazione, rischiosa: un'interruzione di corrente a metà può rendere la macchina inutilizzabile.dmidecodeserve solo a sapere quale versione c'è prima di decidere.
Riepilogo
| Comando | Cosa fa |
|---|---|
sudo dmidecode | Mostra tutta la tabella (lunga: usa less) |
sudo dmidecode -t system | Modello, costruttore e numero di serie |
sudo dmidecode -t bios | Versione e data del BIOS/UEFI |
sudo dmidecode -t memory | Banchi di memoria, uno per uno |
sudo dmidecode -t 16 -q | Capacità massima e numero di slot di memoria |
sudo dmidecode -t processor | Il processore (zoccolo, versione, velocità) |
sudo dmidecode -s system-serial-number | Una sola stringa, per gli script |
sudo dmidecode -s | Elenca le parole chiave valide per -s |
sudo dmidecode --dump-bin file | Salva la tabella grezza in un file |
dmidecode --from-dump file | Rilegge un file salvato, anche su un'altra macchina |
cat /sys/class/dmi/id/product_name | Il modello, senza dmidecode |