Як видалити старі ядра Ubuntu і звільнити /boot
Якщо /boot заповнено пакетами linux-image, apt перестає налаштовувати пакети. Дізнайтеся, які ядра можна безпечно видалити, і збережіть запущене.
Чому apt припиняє працювати, коли /boot заповнюється старими ядрами
В Ubuntu кожне оновлення ядра записує новий набір файлів у /boot і залишає попередні файли на місці. Через це невеликий розділ /boot заповнюється, і apt більше не може завершити встановлення. Відновлення виконується у два кроки. Визначте, які пакети в системі є ядрами, і яке ядро запущено, а потім видаліть решту за допомогою apt autoremove --purge.
Порядок дій важливий. Запущене ядро — це пакет, який не можна видаляти. Система також може вже перебувати у стані, коли apt взагалі не запускається. Спочатку виконайте діагностику.
Як насправді виглядає збій
Версія ядра встановлює два великі файли в /boot: стиснене ядро (vmlinuz-<version>) та initramfs (початкова файлова система RAM, initrd.img-<version> — невеликий архів, який ядро розпаковує перед монтуванням кореневої файлової системи). Initramfs створюється на вашій машині під час встановлення, тому для встановлення потрібне вільне місце, а не лише пропускна здатність для завантаження. Якщо вільного місця не залишилося, збірка завершується помилкою, і разом із нею не належно налаштовується пакет.
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 1Рядок із версією буде відповідати вашій системі. Назва компресора визначається значенням у COMPRESS= в /etc/initramfs-tools/initramfs.conf, тому в новішому образі може бути вказано zstd, а в старішому — gzip. Два рядки, які вказують на цю проблему, — це No space left on device і рядок dpkg: error processing package під ним.
Після цього пакет залишається частково налаштованим. Кожен наступний запуск apt знову намагається налаштувати його, завершується такою самою помилкою та закінчується повідомленням E: Sub-process /usr/bin/dpkg returned an error code (1). Це важливо не лише через нестачу дискового простору: unattended-upgrades запускається за розкладом, отримує ту саму помилку й зупиняється. Сервер здається працездатним, але непомітно припиняє встановлювати оновлення безпеки. Це також означає, що будь-яке незалежне встановлення, яке ви спробуєте виконати, завершується тим самим рядком, а причина помилки приписується пакету, який ви додавали в цей момент. Саме тому помилку встановлення Tailscale в Ubuntu варто спочатку розглядати як помилку apt. Якщо apt update завершується помилкою ще до цього етапу, це окрема проблема, часто дубльований запис після переходу джерел на формат deb822.
Перевірте, чи є /boot окремим розділом
Перш ніж щось видаляти, з’ясуйте, який обсяг ви фактично звільняєте.
findmnt /boot
findmnt -T /boot
df -h /boot /Перша команда виводить рядок лише тоді, коли /boot є окремою точкою монтування. Друга команда виводить результат завжди та називає файлову систему, на якій фактично розташований /boot. Якщо обидві команди називають ту саму файлову систему, що й /, тоді /boot — це лише каталог у кореневій файловій системі, і він не може заповнитися окремо: коренева файлова система переповнена, а старі ядра є лише однією з кількох причин. У такому разі sudo apt clean, яка видаляє завантажені файли .deb у каталозі /var/cache/apt/archives, звільнить місце. На машині зі справжнім розділом /boot команда apt clean взагалі не звільнить там місця, оскільки кеш розташований в іншій файловій системі.
Тепер визначте значення, з яким ви працюватимете.
df -h /boot
ls -lh /boot/vmlinuz-$(uname -r) /boot/initrd.img-$(uname -r)Порівняйте стовпець Avail із розміром цих двох файлів. Файл initrd більший. Для наступного оновлення ядра знадобиться місце ще для однієї пари файлів приблизно такого самого розміру, тому якщо Avail менше за поточний initrd, наступне оновлення вже завершиться помилкою.
Знайдіть ядро, під яким працює система
uname -r
cat /var/run/reboot-required.pkgsuname -r виводить рядок release ядра, завантаженого в пам’ять. Скопіюйте цей рядок в окреме місце. Це версія, яку не можна видаляти.
Другий файл існує лише тоді, коли пакет запросив перезавантаження. Рядок linux-image у ньому означає, що новіше ядро вже встановлено на диску, але не використовується, оскільки після його встановлення систему не перезавантажували. Якщо можливо, перезавантажте систему перед очищенням. apt захищає запущене ядро та найновіше ядро, тому очищення під час роботи зі старим ядром залишає закріпленою ще одну непотрібну версію.
Перелік пакетів ядра та перевірка їхніх станів
dpkg --list | grep -E 'linux-(image|modules|headers|tools)' | awk '{print $1, $2}'Перше поле — це код стану пакета в dpkg. ii означає, що пакет встановлено та налаштовано. iF означає, що пакет встановлено, але налаштовано лише частково. Саме такий стан залишає описане вище невдале оновлення. rc означає, що пакет видалено, але його конфігурацію все ще збережено на диску. Такий пакет не займає місця в /boot, тому його можна безпечно очистити.
Друге поле вказує тип пакета. Назва з версією, наприклад linux-image-6.8.0-64-generic, означає конкретну версію ядра. Назва без версії, наприклад linux-image-generic, linux-headers-generic або linux-generic, означає метапакет. Він не містить ядра. Його єдине призначення — залежати від найновішої версії ядра, щоб apt upgrade встановлював нові ядра. Видалення метапакета припиняє отримання оновлень ядра, і після цього система вас про це не попереджає.
Пакети поділяються на такі сімейства. linux-image-* містить стиснений образ ядра в /boot. linux-modules-* і linux-modules-extra-* містять драйвери в /lib/modules. linux-headers-* містить заголовки для збирання в /usr/src. Отже, очищення заголовків звільняє місце у файловій системі root, але не в /boot. Якщо проблема полягає в заповненому розділі /boot, потрібно шукати пакети з образами ядра.
ls -1 /boot/vmlinuz-*
ls -1 /lib/modules/Ці два переліки мають узгоджуватися між собою та з результатом dpkg --list. Каталог у /lib/modules, для якого немає відповідного встановленого пакета, є залишком після ручного видалення файлів.
Як apt визначає, які ядра залишати
apt autoremove не видалятиме ядро, яке вважає захищеним. До захищеного набору входить ядро, під яким ви працюєте зараз. Політика зберігання відрізняється між випусками Ubuntu, тому перегляньте її на власній машині, а не покладайтеся на число, записане десь заздалегідь.
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 — це список шаблонів імен пакетів, яких apt autoremove не видаляє. APT::VersionedKernelPackages — це список префіксів імен, за якими apt спочатку визначає пакети версійованих ядер. У випусках, де створюється /etc/apt/apt.conf.d/01autoremove-kernels, цей файл щоразу перезаписує /etc/kernel/postinst.d/apt-auto-removal під час встановлення пакета ядра. Тому ручне редагування нічого не дає: наступне встановлення ядра перезапише внесені зміни. У випусках, де файл відсутній, apt застосовує такий самий захист внутрішньо. У будь-якому разі apt-config dump показує правила, чинні на вашій системі. Саме цей вивід є правильною відповіддю для вашого випуску.
Безпечне очищення
sudo apt update
sudo apt autoremove --purge --dry-run--dry-run не змінює дані на диску та виводить точний список того, що буде видалено під час фактичного запуску. Перегляньте цей список. Дві речі мають вас зупинити. Мета-метапакет, наприклад linux-generic або linux-image-generic, у списку видалення означає, що його позначено як автоматично встановлений. Його видалення припинить оновлення ядра. Рядок із uname -r у списку видалення означає, що запущене ядро не захищене від видалення. Такого не повинно бути. Перед продовженням потрібно з’ясувати причину.
Якщо список правильний, виконайте команду фактично.
sudo apt autoremove --purge
df -h /bootКоманда --purge також видаляє залишкову конфігурацію разом із пакетом. Вона звільняє лише трохи додаткового місця, але запобігає накопиченню рядків rc у dpkg --list. Завдяки цьому наступна перевірка залишається читабельною.
Після цього переконайтеся, що меню завантаження перебудовано. Видалення пакета ядра запускає update-grub, тому меню має містити посилання лише на файли, які досі існують.
sudo grep -o 'vmlinuz-[^ ]*' /boot/grub/grub.cfg | sort -u
ls -1 /boot/vmlinuz-*Кожна версія з першого виводу має з’явитися в другому. Запис меню, який посилається на відсутній файл, може перетворити працездатний сервер на сервер, що зупиняється на запрошенні GRUB. Це один зі сценаріїв, за яких VPS не завантажується після оновлення ядра. Виправити таку проблему з rescue console значно складніше, ніж запобігти їй на цьому етапі.
Чому apt autoremove іноді нічого не видаляє
apt autoremove видаляє лише пакети, позначені як встановлені автоматично, тобто пакети, які було встановлено як залежність іншого пакета. Ядро, яке ви встановили самостійно за допомогою apt install linux-image-6.8.0-40-generic, позначене як встановлене вручну, тому autoremove не видалить його, навіть якщо воно дуже старе.
apt-mark showmanual | grep -E '^linux-'Будь-яке версійоване ядро в цьому виводі невидиме для autoremove. Позначте його як встановлене автоматично, використовуючи рядки версій із власного списку:
sudo apt-mark auto linux-image-6.8.0-40-generic linux-modules-6.8.0-40-generic
sudo apt autoremove --purge --dry-runЗалиште метапакети позначеними як встановлені вручну. Вони мають бути встановлені вручну, оскільки саме їх ви запитували встановити.
Навмисно видаліть одну вказану версію ядра
Іноді потрібно видалити певну версію негайно, а не чекати, доки це дозволить політика. Вкажіть пакет образу, а apt визначить решту залежностей.
sudo apt purge linux-image-6.8.0-40-genericapt спочатку виводить список пакетів для видалення, а вже потім виконує операцію, оскільки linux-modules-extra-* залежить від пакета образу й має бути видалений у межах тієї самої транзакції. Цей список є фактичною перевіркою безпеки. Саме в ньому можна побачити, що разом із потрібною версією видаляється метапакет. Якщо в списку є щось неочікуване, дайте відповідь n. Після цього виконайте sudo apt autoremove --purge, щоб видалити пакети модулів і заголовків, які більше не потрібні.
Чому не можна видаляти запущене ядро
Ядро, яке вже завантажене в пам’ять, продовжує працювати після видалення його файлів, тому спочатку проблем не видно. Несправним стає все, що ядро ще не встигло завантажити. Очищення linux-modules-$(uname -r) видаляє /lib/modules/$(uname -r)/, тому наступне завантаження модуля завершується помилкою:
modprobe: FATAL: Module nf_tables not found in directory /lib/modules/6.8.0-64-genericПісля цього не вдається перезавантажити конфігурацію firewall. Також не вдається змонтувати тип файлової системи, до якого це ядро не зверталося після завантаження. Водночас /boot/vmlinuz-$(uname -r) видалено, тому меню завантаження більше не пропонує ядро, під яким працює система, і під час наступного перезавантаження система завантажиться інакше. Машина продовжує обслуговувати мережевий трафік, але вже не може завантажитися. Щоразу перевіряйте uname -r за списком на видалення.
Коли в /boot недостатньо місця для запуску apt
Саме через такий стан користувачі знаходять цю сторінку. apt autoremove потребує dpkg, щоб спочатку завершити налаштування частково налаштованого пакета ядра. На цьому етапі перебудовується initramfs, для якого потрібне місце в /boot, а його немає. Один раз вручну розірвіть цей цикл.
uname -r
ls -1 /boot/initrd.img-*Виберіть один initrd, версія якого не збігається з рядком, який повернув uname -r, і видаліть лише цей файл.
sudo rm /boot/initrd.img-6.8.0-40-generic
sudo apt --fix-broken install
sudo apt autoremove --purge
sudo update-grubКожен рядок має своє призначення. rm є навмисним винятком: він залишає dpkg з думкою, що файл існує, хоча насправді його немає. apt --fix-broken install завершує налаштування, яке завершилося помилкою, оскільки тепер для initramfs є місце. Потім autoremove --purge видаляє пакет, файл якого ви видалили, разом з іншими старими версіями. Це знову узгоджує dpkg із фактичним станом диска. update-grub перебудовує меню на основі файлів, які справді існують. Не перезавантажуйте систему між rm і update-grub, оскільки в цей проміжок меню все ще може посилатися на щойно видалений файл. Якщо dpkg повідомляє, що операцію перервано, sudo dpkg --configure -a виконує таке саме відновлення, як apt --fix-broken install.
Та сама процедура в системах із dnf
Якщо ваш VPS працює під керуванням Fedora або одного з перебудованих дистрибутивів RHEL, наприклад Rocky Linux, механізм працює навпаки. Debian і Ubuntu захищають ядра за допомогою правил автоматичного видалення apt і залишають очищення вам або запускають його через unattended-upgrades, тоді як dnf дотримується обмеження, яке називається installonly_limit, і автоматично видаляє найстаріше ядро, щойно нове встановлення перевищило б це обмеження. Перевірте поточне значення за допомогою grep installonly_limit /etc/dnf/dnf.conf і man 5 dnf.conf, а наявні старі ядра видаліть за допомогою sudo dnf remove --oldinstallonly. Запущене ядро також захищене. Загальне зіставлення команд цих двох пакетних менеджерів наведено в матеріалі еквіваленти команд dnf і apt.
Запобігайте повторенню проблеми
Очищення, яке залежить від того, чи ви про нього пам’ятаєте, зрештою не спрацює. Тому додайте його до компонента, який встановлює ядра. Відкрийте /etc/apt/apt.conf.d/50unattended-upgrades і знайдіть ці ключі. Файл, що постачається з пакетом, уже містить їх як закоментовані рядки:
Unattended-Upgrade::Remove-Unused-Kernel-Packages "true";
Unattended-Upgrade::Remove-Unused-Dependencies "true";Розкоментуйте їх, а не додавайте другу копію в кінці файлу. У конфігурації apt застосовується останнє присвоєння ключа. Тому дубльований ключ створює суперечність у файлі та приховує фактичне значення. Перевірте результат обробки конфігурації та перегляньте запуск, який нічого не змінює:
apt-config dump | grep -i 'Unattended-Upgrade::Remove'
sudo unattended-upgrade --dry-run --debug
sudo tail -n 40 /var/log/unattended-upgrades/unattended-upgrades.logЖурнал є підтвердженням. У ньому записується кожен запуск. Тому невдале оновлення через нестачу місця з’явиться в журналі задовго до того, як хтось помітить, що на машині не встановлено актуальні оновлення. Інші параметри цієї конфігурації описано в розділі автоматичні оновлення безпеки в Ubuntu.
Перед встановленням наступного ядра потрібно перевірити одне значення. Для цього використовуються ті самі дві команди, що й на початку цього посібника:
df -h /boot
ls -lh /boot/initrd.img-$(uname -r)Якщо Avail не перевищує розмір цього файлу із достатнім запасом, наступне ядро не встановиться саме з описаної вище причини. Виправте це зараз, а не під час оновлення. Таку перевірку варто виконувати протягом хвилини разом з іншими перевірками стану диска на VPS. Вона особливо важлива безпосередньо перед оновленням випуску, оскільки перехід з Ubuntu 24.04 на 26.04 встановлює нове ядро на початковому етапі, а do-release-upgrade припинить роботу, якщо в /boot недостатньо вільного місця.
FAQ
Чому Ubuntu зберігає старі ядра, а не видаляє їх?
Тому що ядро, яке не запускається, залишає вас без інших варіантів для вибору. Збереження попередньої версії дає змогу відновитися після невдалого оновлення через меню GRUB, а не через rescue console провайдера. apt тому захищає набір kernel packages від автоматичного видалення, завжди включаючи версію, під якою ви працюєте. Виконайте apt-config dump | grep -i neverautoremove, щоб переглянути точні шаблони, які захищає ваш release, оскільки політика відрізняється між releases.
Чи безпечно виконувати apt autoremove --purge на production server?
Так, якщо спочатку переглянути dry run. Виконайте sudo apt autoremove --purge --dry-run, який нічого не записує, і перевірте список у виводі. Зупиніться, якщо в ньому є meta package, наприклад linux-generic або linux-image-generic, оскільки видалення одного з них припинить майбутні оновлення ядра. Також зупиніться, якщо в списку є version string, яку виводить uname -r. Якщо немає ні того, ні іншого, будуть видалені старі ядра та orphaned dependencies.
apt autoremove нічого не видалив, а /boot досі заповнений. Що робити?
Старі ядра майже напевно позначені як manual, а autoremove обробляє лише пакети, позначені як automatic. Виконайте apt-mark showmanual | grep -E '^linux-'. Будь-яке versioned kernel, наведене в цьому списку, свого часу було встановлено вручну. Позначте його як automatic за допомогою sudo apt-mark auto linux-image-<version> і знову виконайте dry run або безпосередньо видаліть цю версію за допомогою sudo apt purge linux-image-<version>.
Чи можна вручну видалити файли з /boot?
Лише як свідомий одноразовий захід, коли /boot настільки заповнений, що apt не може налаштувати пошкоджений kernel package. Видаліть один файл initrd.img-<version>, версія якого не збігається з виводом uname -r, а потім негайно виконайте sudo apt --fix-broken install, sudo apt autoremove --purge і sudo update-grub. Видалення файлів без цих подальших дій залишає dpkg записи про пакети, файли яких уже відсутні, а в меню GRUB — записи, що вказують на відсутні файли. У результаті машина не запуститься під час наступного перезавантаження, а не в момент, коли ви припустилися помилки.