Come liberare spazio in /boot su Ubuntu dai vecchi kernel
Quando /boot è piena, apt può mostrare errori e interrompere le installazioni. Scopri quali kernel rimuovere in sicurezza e conserva quello in esecuzione.
Perché apt smette di funzionare quando /boot si riempie di kernel obsoleti
Su Ubuntu, ogni aggiornamento del kernel scrive un nuovo insieme di file in /boot e lascia in posizione quelli precedenti. Di conseguenza, una partizione /boot di piccole dimensioni si riempie e apt non riesce più a completare un'installazione. La riparazione richiede due passaggi. Individuare quali pacchetti presenti sul sistema sono kernel e quale kernel è in esecuzione, quindi rimuovere gli altri con apt autoremove --purge.
L'ordine è importante. Il kernel in esecuzione è il pacchetto che non deve essere rimosso. Inoltre, il sistema potrebbe trovarsi già in uno stato in cui apt non può essere eseguito. Eseguire prima la diagnosi.
Come si presenta realmente il problema
Una versione del kernel installa due file di grandi dimensioni in /boot: il kernel compresso (vmlinuz-<version>) e l’initramfs (initial RAM filesystem, initrd.img-<version>, il piccolo archivio che il kernel decomprime prima di montare la root reale). L’initramfs viene creato sul computer durante l’installazione. Per questo l’installazione richiede spazio libero, non soltanto banda per il download. Se non rimane spazio, la compilazione non riesce e il pacchetto entra a sua volta in errore.
update-initramfs: Generating /boot/initrd.img-6.8.0-64-generic
gzip: stdout: No space left on device
E: mkinitramfs failure gzip 1
update-initramfs: failed for /boot/initrd.img-6.8.0-64-generic with 1.
dpkg: error processing package linux-image-6.8.0-64-generic (--configure):
installed linux-image-6.8.0-64-generic package post-installation script subprocess returned error exit status 1La stringa della versione sarà quella del tuo sistema. Il nome del compressore proviene da COMPRESS= in /etc/initramfs-tools/initramfs.conf. Per questo un’immagine recente può indicare zstd, mentre una precedente può indicare gzip. Le due righe che identificano questo problema sono No space left on device e la riga dpkg: error processing package sottostante.
Dopodiché il pacchetto resta in stato di configurazione parziale. Ogni esecuzione successiva di apt tenta di configurarlo di nuovo, non riesce nello stesso modo e termina con E: Sub-process /usr/bin/dpkg returned an error code (1). Questo è l’aspetto importante oltre alla mancanza di spazio: unattended-upgrades viene eseguito secondo la pianificazione, incontra lo stesso errore e si interrompe. Il server sembra funzionare normalmente, ma smette senza segnalarlo di applicare gli aggiornamenti di sicurezza. Inoltre, qualsiasi installazione non correlata che tenti di eseguire non riesce con la stessa riga di errore, che viene attribuita all’elemento aggiunto in quel momento. Per questo vale la pena leggere un’installazione di Tailscale che non riesce su Ubuntu considerandola innanzitutto un errore di apt. Se apt update non riesce prima di arrivare a questo punto, si tratta di un problema distinto, spesso una voce duplicata dopo la migrazione delle sorgenti a deb822.
Verificare se /boot è una partizione separata
Prima di eliminare qualsiasi elemento, verifica quale spazio stai effettivamente liberando.
findmnt /boot
findmnt -T /boot
df -h /boot /Il primo comando stampa una riga solo se /boot è un proprio punto di mount. Il secondo stampa sempre una riga e indica il filesystem che contiene realmente /boot. Se entrambi indicano lo stesso filesystem di /, allora /boot è soltanto una directory del filesystem root e non può riempirsi autonomamente: il filesystem root è pieno e i kernel obsoleti sono solo una delle possibili cause. In questo caso sudo apt clean, che elimina i file .deb scaricati nella directory /var/cache/apt/archives, libera spazio. Su una macchina con una partizione /boot effettiva, apt clean non libera invece alcuno spazio in quella partizione, perché la cache si trova su un filesystem diverso.
Ora recupera il valore di riferimento.
df -h /boot
ls -lh /boot/vmlinuz-$(uname -r) /boot/initrd.img-$(uname -r)Confronta la colonna Avail con le dimensioni dei due file. L'initrd è il file più grande. Il prossimo aggiornamento del kernel richiederà spazio per un'altra coppia di file di dimensioni all'incirca equivalenti. Se Avail è inferiore alle dimensioni dell'initrd corrente, il prossimo aggiornamento non riuscirà già a essere eseguito.
Individuare il kernel in esecuzione
uname -r
cat /var/run/reboot-required.pkgsuname -r stampa la stringa di release del kernel attualmente caricato in memoria. Copiare quella stringa in un luogo sicuro. Corrisponde alla versione che non deve essere rimossa.
Il secondo file esiste solo quando un pacchetto ha richiesto un riavvio. Una riga linux-image al suo interno indica che sul disco è installato un kernel più recente, ma non utilizzato, perché la macchina non è stata riavviata dopo la sua installazione. Se possibile, riavviare prima della pulizia. apt protegge il kernel in esecuzione e quello più recente; quindi, se si esegue la pulizia mentre è attivo un kernel meno recente, rimane bloccata una versione aggiuntiva rispetto al necessario.
Elenca i pacchetti del kernel e verifica il loro stato
dpkg --list | grep -E 'linux-(image|modules|headers|tools)' | awk '{print $1, $2}'Il primo campo è il codice di stato di dpkg. ii indica che il pacchetto è installato e configurato. iF indica che è installato ma configurato solo parzialmente, esattamente la situazione lasciata dall'aggiornamento non riuscito precedente. rc indica che il pacchetto è stato rimosso, ma la relativa configurazione è ancora presente sul disco. Non occupa spazio in /boot e può essere rimosso definitivamente senza rischi.
Il secondo campo indica il tipo di pacchetto. Un nome che contiene una versione, come linux-image-6.8.0-64-generic, identifica uno specifico kernel. Un nome senza versione, come linux-image-generic, linux-headers-generic o linux-generic, identifica un meta pacchetto. Non contiene alcun kernel. Il suo unico scopo è dipendere dal kernel con la versione più recente, in modo che apt upgrade installi i nuovi kernel. Rimuovendo un meta pacchetto, la macchina non riceve più gli aggiornamenti del kernel e in seguito non viene visualizzato alcun avviso.
Le famiglie sono suddivise nel modo seguente. linux-image-* contiene il kernel compresso in /boot. linux-modules-* e linux-modules-extra-* contengono i driver in /lib/modules. linux-headers-* contiene gli header necessari alla compilazione in /usr/src. Di conseguenza, la rimozione definitiva degli header libera spazio nel filesystem root, non nello spazio di /boot. Se il problema riguarda una partizione /boot piena, devi cercare i pacchetti delle immagini del kernel.
ls -1 /boot/vmlinuz-*
ls -1 /lib/modules/Questi due elenchi dovrebbero corrispondere tra loro e anche all'output di dpkg --list. Una directory in /lib/modules senza un pacchetto installato corrispondente è un residuo di una precedente rimozione manuale dei file.
Come apt decide quali kernel mantenere
apt autoremove non rimuove un kernel che considera protetto. L’insieme dei kernel protetti include quello attualmente in esecuzione. La policy di conservazione è cambiata tra le diverse release di Ubuntu. Leggila quindi direttamente sul tuo sistema, senza affidarti a un numero riportato altrove.
apt-config dump | grep -i -e neverautoremove -e versionedkernel
ls -l /etc/apt/apt.conf.d/01autoremove /etc/apt/apt.conf.d/01autoremove-kernelsAPT::NeverAutoRemove è l’elenco dei pattern dei nomi dei pacchetti che apt autoremove rifiuta di modificare. APT::VersionedKernelPackages è l’elenco dei prefissi dei nomi che apt considera innanzitutto pacchetti kernel versionati. Nelle release che generano /etc/apt/apt.conf.d/01autoremove-kernels, quel file viene riscritto da /etc/kernel/postinst.d/apt-auto-removal ogni volta che viene installato un pacchetto kernel. Modificarlo manualmente non serve: la successiva installazione di un kernel sovrascrive la modifica. Nelle release in cui il file non è presente, apt applica la stessa protezione internamente. In entrambi i casi, apt-config dump mostra le regole attive sul tuo sistema. Quell’output è la risposta corretta per la tua release.
La pulizia che è sicuro eseguire
sudo apt update
sudo apt autoremove --purge --dry-run--dry-run non modifica nulla sul disco e mostra esattamente ciò che l'esecuzione effettiva rimuoverebbe. Leggere l'elenco. Due elementi richiedono di interrompere la procedura. Un metapacchetto come linux-generic o linux-image-generic nell'elenco di rimozione indica che è stato classificato come installato automaticamente; rimuoverlo interrompe gli aggiornamenti del kernel. La stringa restituita da uname -r nell'elenco di rimozione indica che il kernel in esecuzione non è protetto. Non dovrebbe accadere e deve essere analizzato prima di procedere.
Se l'elenco è corretto, eseguire il comando effettivamente.
sudo apt autoremove --purge
df -h /bootLa modalità --purge rimuove anche la configurazione residua, oltre al pacchetto. Libera poco spazio aggiuntivo e mantiene dpkg --list privo di righe rc accumulate, così il controllo successivo resta leggibile.
Verificare quindi che il menu di avvio sia stato ricostruito. La rimozione di un pacchetto del kernel esegue automaticamente update-grub, quindi il menu dovrebbe fare riferimento soltanto a file ancora esistenti.
sudo grep -o 'vmlinuz-[^ ]*' /boot/grub/grub.cfg | sort -u
ls -1 /boot/vmlinuz-*Ogni versione restituita dal primo comando deve comparire anche nel secondo. Una voce del menu che punta a un file non più esistente può trasformare un server funzionante in un server che si arresta al prompt di GRUB. Questo è uno dei modi in cui si può arrivare a un VPS che non si avvia dopo un aggiornamento del kernel e risolvere il problema da una console di ripristino è molto più difficile che evitarlo in questa fase.
Perché apt autoremove a volte non rimuove nulla
apt autoremove rimuove soltanto i pacchetti contrassegnati come automatici, cioè i pacchetti installati come dipendenza di un altro pacchetto. Un kernel installato manualmente con apt install linux-image-6.8.0-40-generic è contrassegnato come manuale e autoremove non lo rimuoverà mai, indipendentemente dalla sua età.
apt-mark showmanual | grep -E '^linux-'Qualsiasi kernel con versione presente in quell'output non viene considerato da autoremove. Impostalo nuovamente come automatico usando le stringhe di versione del tuo elenco:
sudo apt-mark auto linux-image-6.8.0-40-generic linux-modules-6.8.0-40-generic
sudo apt autoremove --purge --dry-runLascia i meta-pacchetti contrassegnati come manuali. Devono essere manuali, perché sono i pacchetti che hai richiesto esplicitamente.
Rimuovere intenzionalmente un kernel specifico
A volte è necessario rimuovere subito una versione specifica, invece di attendere che la policy lo consenta. Indicate il pacchetto dell'immagine e lasciate che apt determini il resto.
sudo apt purge linux-image-6.8.0-40-genericapt visualizza un elenco di rimozione prima di eseguire qualsiasi operazione, perché linux-modules-extra-* dipende dal pacchetto dell'immagine e deve essere rimosso nella stessa transazione. Questo elenco è il controllo di sicurezza effettivo: qui potete verificare se, insieme alla versione da rimuovere, viene eliminato anche un meta-pacchetto. Rispondete n se contiene elementi imprevisti. Eseguite quindi sudo apt autoremove --purge per raccogliere i pacchetti dei moduli e degli header che non sono più necessari.
Perché non rimuovere mai il kernel in esecuzione
Il kernel già presente in memoria continua a funzionare dopo l’eliminazione dei relativi file, quindi inizialmente non sembra esserci alcun problema. Il problema riguarda tutto ciò che il kernel non ha ancora caricato. L’eliminazione di linux-modules-$(uname -r) rimuove /lib/modules/$(uname -r)/, quindi il caricamento successivo di un modulo non riesce:
modprobe: FATAL: Module nf_tables not found in directory /lib/modules/6.8.0-64-genericDa quel momento il ricaricamento del firewall non riesce più, così come il montaggio di un tipo di filesystem che questo kernel non ha utilizzato dall’avvio. Nel frattempo /boot/vmlinuz-$(uname -r) non esiste più, quindi il menu di avvio non propone più il kernel attualmente in esecuzione e il riavvio successivo avvia un kernel diverso. La macchina continua a gestire il traffico, ma non è più avviabile. Controllare sempre uname -r rispetto all’elenco degli elementi da rimuovere.
Quando /boot è troppo piena perché apt possa essere eseguito
Questa è la situazione che porta gli utenti a cercare questa pagina. apt autoremove deve eseguire dpkg per completare prima la configurazione del pacchetto del kernel parzialmente configurato. Questo passaggio ricrea un initramfs e richiede spazio in una /boot che non ne ha più. Interrompere manualmente il ciclo una sola volta.
uname -r
ls -1 /boot/initrd.img-*Scegliere un initrd con una versione diversa dalla stringa restituita da uname -r e eliminare solo quel file.
sudo rm /boot/initrd.img-6.8.0-40-generic
sudo apt --fix-broken install
sudo apt autoremove --purge
sudo update-grubOgni riga ha uno scopo preciso. rm è un'eccezione intenzionale: lascia dpkg convinto che un file esista anche se non esiste. apt --fix-broken install completa la configurazione non riuscita, ora che c'è spazio per l'initramfs. autoremove --purge rimuove quindi il pacchetto corrispondente al file eliminato, insieme alle altre versioni precedenti, riallineando dpkg al contenuto effettivo del disco. update-grub ricrea il menu in base ai file realmente presenti. Non riavviare tra rm e update-grub, perché in quel periodo il menu può ancora puntare al file appena eliminato. Se dpkg segnala che l'operazione è stata interrotta, sudo dpkg --configure -a esegue la stessa correzione di apt --fix-broken install.
Lo stesso lavoro sui sistemi dnf
Se il tuo VPS esegue Fedora o una delle ricompilazioni di RHEL, come Rocky Linux, il meccanismo è invertito. Debian e Ubuntu proteggono i kernel con le regole apt autoremove e lasciano a te, oppure a unattended-upgrades, l'esecuzione della pulizia, mentre dnf applica un limite chiamato installonly_limit e rimuove automaticamente il kernel più vecchio non appena una nuova installazione lo supererebbe. Leggi il valore attivo con grep installonly_limit /etc/dnf/dnf.conf e man 5 dnf.conf, quindi svuota le versioni arretrate esistenti con sudo dnf remove --oldinstallonly. Anche in questo caso il kernel in esecuzione è protetto. Per una corrispondenza più ampia tra i due gestori di pacchetti, consulta le equivalenze tra i comandi dnf e apt.
Evita che il problema si ripeta
La pulizia basata sul fatto che tu te ne ricordi prima o poi fallisce. Configurala quindi nel componente che installa i kernel. Apri /etc/apt/apt.conf.d/50unattended-upgrades e cerca queste chiavi, che il file fornito contiene già come righe commentate:
Unattended-Upgrade::Remove-Unused-Kernel-Packages "true";
Unattended-Upgrade::Remove-Unused-Dependencies "true";Decommentale invece di aggiungere una seconda copia alla fine del file. Nella configurazione di apt, prevale l'ultima assegnazione di una chiave. Una duplicazione rende quindi il file incoerente e nasconde quale valore sia effettivo. Controlla il risultato dell'analisi del file e monitora un'esecuzione che non modifica nulla:
apt-config dump | grep -i 'Unattended-Upgrade::Remove'
sudo unattended-upgrade --dry-run --debug
sudo tail -n 40 /var/log/unattended-upgrades/unattended-upgrades.logIl log è la prova. Registra ogni esecuzione. Un aggiornamento che non è riuscito per mancanza di spazio compare quindi nel log molto prima che qualcuno noti che la macchina non riceve le patch. Il resto di questa configurazione è descritto in aggiornamenti automatici della sicurezza su Ubuntu.
Prima dell'installazione del prossimo kernel devi controllare un valore. È lo stesso valore verificato dalla stessa coppia di comandi usata all'inizio di questa guida:
df -h /boot
ls -lh /boot/initrd.img-$(uname -r)Se Avail non è significativamente maggiore di quel file, l'installazione del prossimo kernel fallirà esattamente come descritto sopra. Risolvi quindi il problema subito, non durante l'aggiornamento. Questo controllo richiede un minuto e si integra bene con gli altri controlli dello stato del disco su un VPS. È particolarmente importante subito prima di un aggiornamento di release, perché il passaggio di Ubuntu 24.04 a 26.04 installa un nuovo kernel nelle prime fasi del processo e do-release-upgrade interromperà l'operazione quando /boot non dispone di spazio sufficiente.
FAQ
Perché Ubuntu conserva i kernel obsoleti invece di eliminarli?
Perché un kernel che non si avvia non lascia altre versioni da selezionare. Conservare la versione precedente consente di recuperare da un aggiornamento difettoso tramite il menu di GRUB, anziché tramite la console di ripristino del provider. apt protegge quindi un insieme di pacchetti del kernel dalla rimozione automatica, includendo sempre quello attualmente in esecuzione. Esegui apt-config dump | grep -i neverautoremove per visualizzare i pattern esatti protetti dalla tua release, perché la policy è cambiata tra le diverse release.
È sicuro eseguire apt autoremove --purge su un server di produzione?
Sì, purché tu legga prima la simulazione. Esegui sudo apt autoremove --purge --dry-run, che non modifica nulla, e controlla l’elenco visualizzato. Interrompi l’operazione se contiene un meta-pacchetto come linux-generic o linux-image-generic, perché rimuoverne uno impedisce i futuri aggiornamenti del kernel. Interrompi l’operazione anche se contiene la stringa della versione visualizzata da uname -r. Se non compare nessuno dei due elementi, i pacchetti da rimuovere sono kernel obsoleti e dipendenze orfane.
apt autoremove non ha rimosso nulla e /boot è ancora piena. Cosa posso fare?
È molto probabile che i kernel obsoleti siano marcati come installati manualmente; autoremove interviene soltanto sui pacchetti marcati come automatici. Esegui apt-mark showmanual | grep -E '^linux-'. Qualsiasi kernel con versione elencato è stato installato manualmente in precedenza. Marcane l’installazione come automatica con sudo apt-mark auto linux-image-<version> ed esegui nuovamente la simulazione, oppure elimina direttamente quella versione con sudo apt purge linux-image-<version>.
Posso eliminare manualmente i file da /boot?
Solo come intervento mirato e una tantum, quando /boot è così piena che apt non riesce a configurare il pacchetto del kernel danneggiato. Elimina un singolo file initrd.img-<version> la cui versione non corrisponde all’output di uname -r, quindi esegui immediatamente sudo apt --fix-broken install, sudo apt autoremove --purge e sudo update-grub. Eliminare i file senza questi passaggi successivi lascia dpkg con pacchetti registrati i cui file non esistono più e lascia nel menu di GRUB voci che puntano a file mancanti; la macchina non riesce quindi a riavviarsi al riavvio successivo, invece di mostrare il problema nel momento in cui è stato commesso l’errore.