Rimuovere vecchi kernel Ubuntu e liberare /boot
Quando /boot si riempie, apt non configura più i pacchetti. Scopri quali kernel puoi rimuovere senza rischi e conserva sempre quello attualmente avviato.
Perché apt smette di funzionare quando /boot si riempie di vecchi kernel
Su Ubuntu, ogni aggiornamento del kernel scrive un nuovo insieme di file in /boot e lascia sul posto quelli precedenti. Di conseguenza, una partizione /boot di piccole dimensioni si riempie e apt non riesce più a completare un'installazione. La riparazione prevede due passaggi. Individuare quali pacchetti presenti sul sistema sono kernel e quale kernel è stato avviato, 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 una situazione in cui apt non può essere eseguito. Eseguire prima la diagnosi.
Come si presenta realmente l'errore
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 anche il pacchetto va 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 deriva da COMPRESS= in /etc/initramfs-tools/initramfs.conf. Per questo un'immagine recente può indicare zstd, mentre una precedente indica gzip. Le due righe che identificano questo problema sono No space left on device e la riga dpkg: error processing package sottostante.
Dopo l'errore, il pacchetto rimane configurato parzialmente. Ogni successiva esecuzione di apt prova a 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 rilevante oltre alla mancanza di spazio su disco: unattended-upgrades viene eseguito secondo la pianificazione, incontra lo stesso errore e si interrompe. Il server sembra funzionare correttamente, ma smette silenziosamente di applicare gli aggiornamenti di sicurezza. Inoltre, qualsiasi installazione non correlata che provi a eseguire non riesce con la stessa riga di errore, attribuendo la causa al componente che stavi aggiungendo. Per questo vale la pena leggere un'installazione di Tailscale che non riesce su Ubuntu innanzitutto come 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 realmente liberando.
findmnt /boot
findmnt -T /boot
df -h /boot /Il primo comando stampa una riga solo se /boot è un punto di mount separato. Il secondo stampa sempre una riga e indica il filesystem che contiene effettivamente /boot. Se indicano lo stesso filesystem di /, /boot è soltanto una directory del filesystem root e non può riempirsi da sola: il filesystem root è pieno e i kernel obsoleti sono solo una delle possibili cause. In questo caso, sudo apt clean, che svuota i file .deb scaricati in /var/cache/apt/archives, libera spazio. Su una macchina con una vera partizione /boot, apt clean non libera alcuno spazio in quella partizione, perché la cache si trova su un filesystem diverso.
Ora determina 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 richiede spazio per un'altra coppia di file di dimensioni approssimativamente uguali; quindi, se Avail è più piccola dell'initrd attuale, il prossimo aggiornamento non andrà a buon fine.
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 questa stringa in un luogo sicuro. È la versione che non deve essere rimossa.
Il secondo file esiste soltanto quando un pacchetto ha richiesto un riavvio. Una riga linux-image al suo interno indica che su 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; eseguire la pulizia mentre è in uso un kernel precedente mantiene quindi una versione aggiuntiva bloccata, oltre a quelle necessarie.
Elencare i pacchetti del kernel e leggerne gli stati
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, cioè esattamente nello stato lasciato 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 ed è sicuro eliminarlo con purge.
Il secondo campo indica il tipo di pacchetto. Un nome che contiene una versione, come linux-image-6.8.0-64-generic, identifica un kernel specifico. 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. La rimozione di un meta pacchetto impedisce alla macchina di ricevere gli aggiornamenti del kernel e in seguito non viene visualizzato alcun avviso.
Le famiglie sono suddivise come segue. linux-image-* contiene l'immagine compressa del kernel 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. L'eliminazione degli header libera spazio nel filesystem root, non nello spazio /boot. Se il problema riguarda una partizione /boot piena, devi cercare i pacchetti delle immagini.
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 lasciato dalla rimozione manuale dei file.
Come apt decide quali kernel mantenere
apt autoremove non rimuove un kernel che considera protetto; tra i kernel protetti è incluso quello attualmente in esecuzione. La policy di conservazione è cambiata tra le diverse release di Ubuntu. Per questo motivo, leggila direttamente sulla tua macchina invece di 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 con versione. 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 sulla tua macchina. 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 devono far interrompere la procedura. Un metapacchetto come linux-generic o linux-image-generic nell'elenco di rimozione indica che qualcosa lo ha contrassegnato come automatico; rimuoverlo interrompe gli aggiornamenti del kernel. La stringa di uname -r nell'elenco di rimozione indica che il kernel in esecuzione non è protetto. Non dovrebbe accadere e richiede un'indagine prima di procedere.
Se l'elenco è corretto, eseguire il comando senza simulazione.
sudo apt autoremove --purge
df -h /bootLa modalità --purge elimina anche la configurazione residua, oltre al pacchetto. Libera poco spazio aggiuntivo e mantiene dpkg --list libero dall'accumulo di righe rc, così il controllo successivo resta leggibile.
Verificare quindi che il menu di avvio sia stato ricreato. La rimozione di un pacchetto del kernel esegue update-grub automaticamente, quindi il menu dovrebbe fare riferimento soltanto a file ancora presenti.
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 di 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ò ottenere un VPS che non si avvia dopo un aggiornamento del kernel e risolvere il problema da una console di ripristino è molto più difficile che prevenirlo in questa fase.
Perché apt autoremove a volte non rimuove nulla
apt autoremove rimuove soltanto i pacchetti contrassegnati come automatici, cioè quelli installati come dipendenze 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, anche se diventa molto vecchio.
apt-mark showmanual | grep -E '^linux-'Qualsiasi kernel con versione presente in quell'output è invisibile a autoremove. Contrassegnalo nuovamente come automatico usando le stringhe di versione ottenute dal 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 quelli che hai richiesto esplicitamente.
Rimuovere intenzionalmente uno specifico kernel
A volte è necessario rimuovere subito una versione specifica, invece di attendere il momento previsto dalla policy. Indicate il pacchetto image e lasciate che apt determini il resto.
sudo apt purge linux-image-6.8.0-40-genericapt visualizza un elenco dei pacchetti da rimuovere prima di eseguire qualsiasi operazione, perché linux-modules-extra-* dipende dal pacchetto image e deve essere rimosso nella stessa transazione. Questo elenco è il controllo di sicurezza effettivo. È qui che potete verificare se, insieme alla versione da rimuovere, verrebbe eliminato anche un meta-pacchetto. Rispondete n se l'elenco contiene elementi imprevisti. Eseguite poi sudo apt autoremove --purge per individuare i pacchetti dei moduli e degli header che non sono più necessari.
Perché non devi mai rimuovere il kernel in esecuzione
Il kernel già caricato in memoria continua a funzionare dopo l'eliminazione dei relativi file, quindi inizialmente non sembra rompersi nulla. Si rompono invece tutte le funzioni che il kernel non ha ancora caricato. La rimozione completa di linux-modules-$(uname -r) elimina /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 offre più il kernel in esecuzione e il riavvio successivo avvia un kernel diverso. La macchina continua a gestire il traffico, ma non è più avviabile. Controlla uname -r rispetto all'elenco di rimozione ogni volta.
Quando /boot è troppo pieno perché apt possa essere eseguito
Questa è la situazione che porta a cercare questa pagina. apt autoremove deve eseguire dpkg per completare prima la configurazione del pacchetto del kernel rimasto a metà, ma quel passaggio ricrea un initramfs e richiede spazio in un /boot che non ne ha. Interrompere manualmente il ciclo una sola volta.
uname -r
ls -1 /boot/initrd.img-*Scegli un initrd la cui versione non corrisponda alla stringa restituita da uname -r ed elimina 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 una funzione precisa. rm è un'eccezione intenzionale: fa credere a dpkg che un file esista anche se non esiste. apt --fix-broken install completa la configurazione che era fallita, ora che c'è spazio per l'initramfs. autoremove --purge rimuove quindi il pacchetto a cui apparteneva il file eliminato, insieme alle altre versioni precedenti, riallineando dpkg al contenuto effettivo del disco. update-grub ricrea il menu usando i 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 riparazione di apt --fix-broken install.
Lo stesso compito sui sistemi dnf
Se il tuo VPS esegue Fedora o una delle distribuzioni ricostruite da RHEL, come Rocky Linux, il meccanismo è invertito. Debian e Ubuntu proteggono i kernel con le regole di autoremove di apt 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 gli elementi arretrati esistenti con sudo dnf remove --oldinstallonly. Anche in questo caso il kernel in esecuzione è protetto. Per la corrispondenza più ampia tra i due gestori di pacchetti, consulta l'equivalenza tra i comandi dnf e apt.
Evita che il problema si ripeta
La pulizia che dipende dal fatto che tu te ne ricordi prima o poi fallirà, quindi configurala 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";Rimuovi il commento invece di aggiungere una seconda copia alla fine del file. Nella configurazione di apt, prevale l'ultima assegnazione di una chiave. Una chiave duplicata 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 costituisce la prova. Registra ogni esecuzione, quindi un aggiornamento che ha avuto esito negativo per mancanza di spazio compare nel log molto prima che qualcuno si accorga che la macchina non riceve più le patch. Il resto di questa configurazione è descritto nella procedura per gli aggiornamenti automatici di sicurezza su Ubuntu.
Prima che venga installato il kernel successivo, devi controllare un valore. Si tratta della stessa coppia di comandi usata all'inizio di questa guida:
df -h /boot
ls -lh /boot/initrd.img-$(uname -r)Se Avail non è sufficientemente più grande di quel file, l'installazione del kernel successivo fallirà esattamente come descritto sopra. Risolvi quindi il problema ora, non durante l'aggiornamento. Questo controllo richiede un minuto e si integra 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 kernel nuovo nelle prime fasi della procedura e do-release-upgrade interromperà l'operazione quando /boot non dispone di spazio sufficiente. Se al tuo server LTS non è ancora stato proposto l'aggiornamento, la causa è legata ai tempi di rilascio, non a un problema. Ubuntu infatti blocca gli aggiornamenti da una release LTS alla successiva fino a quando non viene rilasciata la point release 26.04.1, creando una finestra nota per sistemare prima /boot.
FAQ
Perché Ubuntu conserva i kernel precedenti 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 problematico tramite il menu di GRUB, invece di usare la console di ripristino del provider. apt protegge quindi un insieme di pacchetti kernel dalla rimozione automatica e include sempre quello in esecuzione. Esegui apt-config dump | grep -i neverautoremove per visualizzare i pattern esatti protetti dalla tua release, poiché la policy è cambiata tra le diverse release.
È sicuro eseguire apt autoremove --purge su un server di produzione?
Sì, se prima controlli la simulazione. Esegui sudo apt autoremove --purge --dry-run, che non scrive alcun dato, e controlla l'elenco visualizzato. Interrompi l'operazione se contiene un meta-pacchetto come linux-generic o linux-image-generic, perché rimuoverne uno interrompe i futuri aggiornamenti del kernel. Interrompi inoltre l'operazione se contiene la stringa della versione visualizzata da uname -r. Se non compare nessuno dei due elementi, si tratta di kernel precedenti e dipendenze orfane.
apt autoremove non ha rimosso nulla e /boot è ancora pieno. Come procedo?
Quasi certamente i kernel precedenti sono contrassegnati come installati manualmente, mentre autoremove interviene soltanto sui pacchetti contrassegnati come automatici. Esegui apt-mark showmanual | grep -E '^linux-'. Qualsiasi kernel con versione elencato è stato installato manualmente in un determinato momento. Contrassegnalo come automatico con sudo apt-mark auto linux-image-<version> ed esegui di nuovo la simulazione, oppure rimuovi direttamente quella versione con sudo apt purge linux-image-<version>.
Posso eliminare manualmente i file da /boot?
Solo come intervento una tantum deliberato, quando /boot è così pieno che apt non riesce a configurare il pacchetto kernel danneggiato. Elimina un solo 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 eseguire 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. Al riavvio successivo la macchina non si avvia, invece di fallire nel momento in cui hai commesso l'errore.