Jak usunąć stare kernele w Ubuntu i zwolnić /boot
Błąd No space left on device w /boot blokuje aktualizacje apt. Dowiedz się, jak bezpiecznie usunąć zbędne pakiety linux-image, zachowując aktualnie używane jądro systemu.
Dlaczego apt przestaje działać, gdy /boot zapełnia się starymi jernelami
W systemie Ubuntu każda aktualizacja kernela zapisuje nowy zestaw plików w /boot i pozostawia poprzednie, co powoduje, że mała partycja /boot zapełnia się, a apt nie może ukończyć instalacji. Naprawa składa się z dwóch kroków. Należy ustalić, które pakiety w systemie są kernelami, a który z nich jest aktualnie uruchomiony, a następnie usunąć pozostałe za pomocą apt autoremove --purge.
Kolejność działań ma znaczenie. Uruchomiony kernel to jedyny pakiet, którego nie wolno usuwać, a system może znajdować się już w stanie, w którym apt w ogóle nie może zostać uruchomiony. Najpierw należy przeprowadzić diagnostykę.
Jak faktycznie wygląda awaria
Wersja jądra instaluje dwa duże pliki w /boot: skompresowane jądro (vmlinuz-<version>) oraz initramfs (początkowy system plików RAM, initrd.img-<version>, małe archiwum rozpakowywane przez jądro przed zamontowaniem właściwego systemu plików root). Obraz initramfs jest budowany na maszynie w momencie instalacji, dlatego proces ten wymaga wolnego miejsca na dysku, a nie tylko przepustowości łącza. Brak miejsca powoduje niepowodzenie budowania i przerwanie instalacji pakietu.
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 1Ciąg znaków wersji będzie specyficzny dla danego systemu. Nazwa kompresora pochodzi z COMPRESS= w /etc/initramfs-tools/initramfs.conf, więc nowsze obrazy mogą wskazywać na zstd, podczas gdy starsze na gzip. Dwie linie identyfikujące ten problem to No space left on device oraz znajdująca się pod nią linia dpkg: error processing package.
Następnie pakiet pozostaje w stanie częściowej konfiguracji. Każde kolejne uruchomienie apt próbuje ponownie skonfigurować pakiet, kończy się tym samym błędem i wyświetla E: Sub-process /usr/bin/dpkg returned an error code (1). Jest to kluczowy aspekt wykraczający poza kwestię miejsca na dysku: unattended-upgrades uruchamia się zgodnie z harmonogramem, napotyka ten sam błąd i przerywa działanie. Serwer wygląda na sprawny, ale po cichu przestaje pobierać poprawki bezpieczeństwa. Oznacza to również, że każda inna próba instalacji zakończy się tym samym błędem, a wina zostanie przypisana aktualnie dodawanemu pakietowi. Dlatego warto zapoznać się z artykułem instalacja Tailscale kończąca się błędem w systemie Ubuntu, aby w pierwszej kolejności zdiagnozować błąd apt. Jeśli apt update zawiedzie wcześniej, jest to odrębny problem, często wynikający z duplikatu wpisu po migracji źródeł deb822.
Sprawdzenie, czy /boot jest oddzielną partycją
Przed usunięciem jakichkolwiek danych należy ustalić, co faktycznie zostanie zwolnione.
findmnt /boot
findmnt -T /boot
df -h /boot /Pierwsze polecenie wyświetla linię tylko wtedy, gdy /boot stanowi osobny punkt montowania. Drugie polecenie wyświetla wynik zawsze i wskazuje system plików, na którym faktycznie znajduje się /boot. Jeśli oba polecenia wskazują ten sam system plików co /, oznacza to, że /boot jest jedynie katalogiem w głównym systemie plików i nie może zapełnić się niezależnie: główny system plików jest pełny, a stare jądra są tylko jednym z wielu czynników. W takim przypadku sudo apt clean, które czyści pobrane pliki .deb w katalogu /var/cache/apt/archives, pozwoli odzyskać miejsce. Na maszynie z wydzieloną partycją /boot polecenie apt clean nie zwolni tam żadnego miejsca, ponieważ pamięć podręczna znajduje się na innym systemie plików.
Teraz należy uzyskać wartość, w odniesieniu do której będą prowadzone dalsze działania.
df -h /boot
ls -lh /boot/vmlinuz-$(uname -r) /boot/initrd.img-$(uname -r)Należy porównać kolumnę Avail z rozmiarem tych dwóch plików. Plik initrd jest większy. Kolejna aktualizacja jądra wymaga miejsca na kolejną parę plików o zbliżonym rozmiarze, więc jeśli Avail jest mniejsza niż bieżący plik initrd, kolejna aktualizacja zakończy się niepowodzeniem.
Identyfikacja używanego jądra systemu
uname -r
cat /var/run/reboot-required.pkgsuname -r wyświetla ciąg znaków wersji jądra aktualnie załadowanego do pamięci. Należy skopiować ten ciąg. Jest to wersja, której nie wolno usuwać.
Drugi plik istnieje tylko wtedy, gdy pakiet wymagał restartu systemu. Wiersz linux-image w tym pliku oznacza, że nowsze jądro jest zainstalowane na dysku, ale nie jest używane, ponieważ maszyna nie została zrestartowana od momentu jego instalacji. Jeśli to możliwe, przed czyszczeniem należy wykonać restart. apt chroni uruchomione jądro oraz najnowszą wersję, dlatego czyszczenie podczas pracy na starym jądrze powoduje zachowanie większej liczby wersji, niż jest to wymagane.
List the kernel packages and read their states
dpkg --list | grep -E 'linux-(image|modules|headers|tools)' | awk '{print $1, $2}'The first field is dpkg's state code. ii means installed and configured. iF means installed but half-configured, which is exactly what the failed upgrade above leaves behind. rc means removed with its configuration still on disk, which occupies nothing in /boot and is safe to purge.
The second field tells you what kind of package it is. A name with a version inside it, such as linux-image-6.8.0-64-generic, is one specific kernel. A name with no version, such as linux-image-generic, linux-headers-generic or linux-generic, is a meta package. It contains no kernel. Its whole job is to depend on the newest versioned kernel so that apt upgrade pulls new kernels in. Removing a meta package stops the machine receiving kernel updates, and nothing warns you afterwards.
The families divide up like this. linux-image-* holds the compressed kernel in /boot. linux-modules-* and linux-modules-extra-* hold the drivers under /lib/modules. linux-headers-* holds build headers under /usr/src, which means purging headers frees root filesystem space and not /boot space. If your problem is a full /boot partition, the image packages are what you are hunting.
ls -1 /boot/vmlinuz-*
ls -1 /lib/modules/These two listings should line up with each other and with the dpkg --list output. A directory in /lib/modules with no matching installed package is a leftover from someone deleting files by hand.
W jaki sposób apt decyduje, które jądra zachować
apt autoremove nie usunie jądra, które uznaje za chronione, a zbiór chroniony obejmuje jądro aktualnie uruchomione. Zasady retencji zmieniały się pomiędzy wydaniami Ubuntu, dlatego należy sprawdzić je bezpośrednio na własnej maszynie, zamiast polegać na liczbach podanych w dokumentacji.
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 to lista wzorców nazw pakietów, których apt autoremove nie usuwa. APT::VersionedKernelPackages to lista prefiksów nazw, które apt traktuje jako wersjonowane pakiety jądra. W wydaniach, które generują /etc/apt/apt.conf.d/01autoremove-kernels, plik ten jest nadpisywany przez /etc/kernel/postinst.d/apt-auto-removal przy każdej instalacji pakietu jądra, więc ręczna edycja nie przynosi efektu: kolejna instalacja jądra nadpisze zmiany. W wydaniach, w których plik ten nie występuje, apt stosuje te same zasady ochrony wewnętrznie. W obu przypadkach apt-config dump wyświetla reguły obowiązujące w danym systemie i to wyjście stanowi poprawną odpowiedź dla konkretnego wydania.
Bezpieczne czyszczenie systemu
sudo apt update
sudo apt autoremove --purge --dry-runPolecenie --dry-run nie wprowadza zmian na dysku i wyświetla dokładnie to, co zostałoby usunięte w rzeczywistym procesie. Należy przeanalizować listę. Dwie sytuacje powinny skłonić do przerwania operacji. Obecność pakietu meta, takiego jak linux-generic lub linux-image-generic na liście do usunięcia, oznacza, że został on oznaczony jako zainstalowany automatycznie, a jego usunięcie spowoduje przerwanie aktualizacji jądra. Obecność ciągu znaków z uname -r na liście do usunięcia oznacza, że aktualnie uruchomione jądro nie jest chronione, co nie powinno mieć miejsca i wymaga zbadania przed podjęciem dalszych kroków.
Jeśli lista jest poprawna, należy wykonać operację właściwą.
sudo apt autoremove --purge
df -h /bootOpcja --purge usuwa zarówno pozostałości konfiguracji, jak i sam pakiet. Zwalnia to niewielką ilość dodatkowego miejsca i utrzymuje dpkg --list w czystości, zapobiegając gromadzeniu się linii rc, co ułatwia czytelność kolejnych audytów.
Następnie należy potwierdzić, że menu startowe zostało przebudowane. Usunięcie pakietu jądra automatycznie uruchamia update-grub, więc menu powinno odwoływać się wyłącznie do istniejących plików.
sudo grep -o 'vmlinuz-[^ ]*' /boot/grub/grub.cfg | sort -u
ls -1 /boot/vmlinuz-*Każda wersja z pierwszego wyjścia musi pojawić się w drugim. Wpis w menu wskazujący na nieistniejący plik jest przyczyną, dla której działający serwer zatrzymuje się na znaku zachęty GRUB. Jest to jedna z dróg do serwera VPS, który nie uruchamia się po aktualizacji jądra, a naprawa tego błędu z poziomu konsoli ratunkowej jest znacznie trudniejsza niż uniknięcie go na tym etapie.
Dlaczego apt autoremove czasami niczego nie usuwa
apt autoremove usuwa wyłącznie pakiety oznaczone jako automatyczne, czyli takie, które zostały zainstalowane jako zależności innych pakietów. Jądro systemu zainstalowane ręcznie za pomocą apt install linux-image-6.8.0-40-generic jest oznaczone jako zainstalowane manualnie, dlatego autoremove nigdy go nie usunie, niezależnie od jego wieku.
apt-mark showmanual | grep -E '^linux-'Każde jądro z przypisaną wersją widoczne w tym wyjściu jest niewidoczne dla autoremove. Należy je usunąć ręcznie, używając ciągów wersji z własnej listy:
sudo apt-mark auto linux-image-6.8.0-40-generic linux-modules-6.8.0-40-generic
sudo apt autoremove --purge --dry-runPozostaw meta-pakiety oznaczone jako zainstalowane manualnie. Powinny one mieć taki status, ponieważ są to pakiety, których instalację zlecono bezpośrednio.
Celowe usunięcie konkretnego jądra systemu
Czasami zachodzi potrzeba natychmiastowego usunięcia określonej wersji jądra, zamiast oczekiwania na automatyczne działanie polityki systemowej. Należy wskazać nazwę pakietu obrazu, a apt zajmie się resztą operacji.
sudo apt purge linux-image-6.8.0-40-genericapt wyświetla listę pakietów do usunięcia przed wykonaniem jakichkolwiek zmian, ponieważ linux-modules-extra-* zależy od pakietu obrazu i musi zostać usunięty w tej samej transakcji. Wyświetlona lista stanowi właściwe zabezpieczenie; pozwala ona wykryć, czy wraz z usuwaną wersją nie zostanie odinstalowany pakiet meta. W przypadku wykrycia nieoczekiwanych pozycji na liście należy odpowiedzieć n. Następnie należy użyć sudo apt autoremove --purge, aby usunąć pakiety modułów i nagłówków, które utraciły swoje uzasadnienie istnienia.
Dlaczego nigdy nie należy usuwać działającego jądra
Jądro znajdujące się w pamięci operacyjnej kontynuuje pracę po usunięciu jego plików, więc początkowo system wydaje się działać poprawnie. Problemy pojawiają się w momencie, gdy system próbuje załadować elementy, których jądro jeszcze nie wczytało. Usunięcie linux-modules-$(uname -r) powoduje usunięcie /lib/modules/$(uname -r)/, co skutkuje niepowodzeniem ładowania kolejnych modułów:
modprobe: FATAL: Module nf_tables not found in directory /lib/modules/6.8.0-64-genericOd tego momentu przeładowanie firewalla kończy się błędem, podobnie jak montowanie systemu plików, z którym jądro nie miało styczności od momentu uruchomienia. W międzyczasie /boot/vmlinuz-$(uname -r) znika, więc menu startowe nie oferuje już jądra, na którym pracuje system, a kolejny restart kończy się niepowodzeniem. Maszyna nadal obsługuje ruch sieciowy, będąc jednocześnie w stanie uniemożliwiającym rozruch. Zawsze sprawdzaj uname -r przed zatwierdzeniem listy usuwanych pakietów.
Gdy partycja /boot jest zbyt pełna, aby uruchomić apt
Jest to stan, który skłania użytkowników do poszukiwania tej strony. apt autoremove wymaga dpkg, aby najpierw dokończyć konfigurację częściowo skonfigurowanego pakietu jądra, a ten krok przebudowuje initramfs, co wymaga miejsca w /boot, którego brakuje. Należy ręcznie przerwać tę pętlę, wykonując jednorazową operację.
uname -r
ls -1 /boot/initrd.img-*Należy wybrać jeden plik initrd, którego wersja nie jest ciągiem znaków zwróconym przez uname -r, a następnie usunąć ten pojedynczy plik.
sudo rm /boot/initrd.img-6.8.0-40-generic
sudo apt --fix-broken install
sudo apt autoremove --purge
sudo update-grubKażdy wiersz ma swoje uzasadnienie. rm jest celowym wyjątkiem, który sprawia, że dpkg uznaje istnienie pliku, który w rzeczywistości nie istnieje. apt --fix-broken install kończy konfigurację, która wcześniej zakończyła się niepowodzeniem, ponieważ teraz jest wystarczająco dużo miejsca na initramfs. Następnie autoremove --purge usuwa pakiet, którego plik został usunięty, wraz z innymi starymi wersjami, co przywraca zgodność dpkg ze stanem dysku. update-grub przebudowuje menu na podstawie plików, które faktycznie istnieją. Nie należy restartować systemu pomiędzy rm a update-grub, ponieważ w tym czasie menu może nadal wskazywać na usunięty plik. Jeśli dpkg zgłasza przerwanie procesu, sudo dpkg --configure -a wykonuje tę samą naprawę co apt --fix-broken install.
To samo zadanie w systemach dnf
Jeśli VPS korzysta z Fedora lub jednej z dystrybucji bazujących na RHEL, takich jak Rocky Linux, mechanizm działania jest odwrotny. Debian i Ubuntu chronią jądra za pomocą reguł autoremove apt i pozostawiają czyszczenie użytkownikowi lub narzędziu unattended-upgrades, podczas gdy dnf wymusza limit o nazwie installonly_limit i automatycznie usuwa najstarsze jądro, gdy tylko nowa instalacja przekroczy tę liczbę. Odczytaj aktualną wartość za pomocą grep installonly_limit /etc/dnf/dnf.conf i man 5 dnf.conf, a istniejące zaległości wyczyść poleceniem sudo dnf remove --oldinstallonly. Uruchomione jądro jest chronione również w tym przypadku. Szersze zestawienie porównawcze obu menedżerów pakietów znajduje się w odpowiedniki poleceń dnf i apt.
Zapobieganie ponownemu wystąpieniu problemu
Czyszczenie zależne od pamięci administratora ostatecznie zawiedzie, dlatego należy zintegrować je z procesem instalacji kerneli. Otwórz /etc/apt/apt.conf.d/50unattended-upgrades i odszukaj poniższe klucze, które w dostarczonym pliku znajdują się już jako zakomentowane linie:
Unattended-Upgrade::Remove-Unused-Kernel-Packages "true";
Unattended-Upgrade::Remove-Unused-Dependencies "true";Odkomentuj je zamiast dopisywać drugą kopię na końcu pliku. W konfiguracji apt ostatnie przypisanie klucza jest wiążące, więc duplikat powoduje niespójność pliku i utrudnia ustalenie, która wartość jest faktycznie używana. Sprawdź, jakie wartości zostały ostatecznie przyjęte przez parser, i monitoruj przebieg operacji, która nie wprowadza zmian:
apt-config dump | grep -i 'Unattended-Upgrade::Remove'
sudo unattended-upgrade --dry-run --debug
sudo tail -n 40 /var/log/unattended-upgrades/unattended-upgrades.logDziennik stanowi dowód. Rejestruje on każde uruchomienie, więc aktualizacja, która nie powiodła się z powodu braku miejsca, pojawi się w nim na długo przed tym, zanim ktokolwiek zauważy, że maszyna ma zaległości w poprawkach. Pozostała część tej konfiguracji została opisana w automatyczne aktualizacje bezpieczeństwa w Ubuntu.
Zanim pojawi się kolejny kernel, należy sprawdzić jedną wartość; służy do tego ta sama para poleceń, co na początku niniejszego przewodnika:
df -h /boot
ls -lh /boot/initrd.img-$(uname -r)Jeśli Avail nie jest wyraźnie większy niż ten plik, kolejny kernel nie zainstaluje się dokładnie w sposób opisany powyżej, dlatego napraw to teraz, a nie w trakcie aktualizacji. Warto poświęcić minutę na tę kontrolę obok innych testów kondycji dysku na VPS. Ma to największe znaczenie tuż przed aktualizacją wydania, ponieważ przejście z Ubuntu 24.04 na 26.04 instaluje nowy kernel na wczesnym etapie procesu, a do-release-upgrade przerwie działanie, jeśli /boot będzie miało zbyt mało wolnego miejsca.
FAQ
Dlaczego Ubuntu zachowuje stare jądra zamiast je usuwać?
Ponieważ jądro, które nie uruchamia się poprawnie, pozostawia użytkownika bez alternatywy. Zachowanie poprzedniej wersji oznacza, że nieudana aktualizacja jest naprawialna z poziomu menu GRUB, zamiast wymagać użycia konsoli ratunkowej dostawcy. apt chroni zatem zestaw pakietów jądra przed automatycznym usunięciem, zawsze uwzględniając wersję aktualnie uruchomioną. Uruchom apt-config dump | grep -i neverautoremove, aby sprawdzić dokładne wzorce chronione w danej wersji systemu, ponieważ polityka ta zmieniała się między wydaniami.
Czy apt autoremove --purge jest bezpieczne do uruchomienia na serwerze produkcyjnym?
Tak, pod warunkiem wcześniejszego sprawdzenia symulacji. Uruchom sudo apt autoremove --purge --dry-run, co nie wprowadza żadnych zmian, i przejrzyj wygenerowaną listę. Przerwij, jeśli zawiera ona metapakiet, taki jak linux-generic lub linux-image-generic, ponieważ usunięcie jednego z nich kończy przyszłe aktualizacje jądra. Przerwij również, jeśli lista zawiera ciąg wersji wyświetlany przez uname -r. Jeśli żaden z tych elementów nie występuje, usuwane są jedynie stare jądra i osierocone zależności.
apt autoremove nic nie usunęło, a /boot jest nadal pełny. Co teraz?
Stare jądra są niemal na pewno oznaczone jako zainstalowane ręcznie, a autoremove dotyczy tylko pakietów oznaczonych jako automatyczne. Uruchom apt-mark showmanual | grep -E '^linux-'. Każde wymienione tam jądro z numerem wersji zostało w pewnym momencie zainstalowane ręcznie. Oznacz je jako automatyczne za pomocą sudo apt-mark auto linux-image-<version> i ponownie uruchom symulację lub usuń tę konkretną wersję bezpośrednio za pomocą sudo apt purge linux-image-<version>.
Czy mogę ręcznie usuwać pliki z /boot?
Tylko w ramach celowego, jednorazowego działania, gdy /boot jest tak pełne, że apt nie może skonfigurować uszkodzonego pakietu jądra. Usuń pojedynczy plik initrd.img-<version>, którego wersja nie jest wynikiem polecenia uname -r, a następnie natychmiast uruchom sudo apt --fix-broken install, sudo apt autoremove --purge oraz sudo update-grub. Usuwanie plików bez tych kroków naprawczych sprawia, że dpkg rejestruje pakiety, których pliki już nie istnieją, a wpisy w menu GRUB wskazują na brakujące zasoby, co powoduje awarię maszyny przy następnym restarcie, zamiast w momencie popełnienia błędu.