SSD Nodes Learn 🎉 VPS từ $5.50/tháng
Hướng dẫn Matt ConnorBởi Matt Connor · Cập nhật ngày 2026-08-15

Dọn kernel cũ trên Ubuntu, giải phóng /boot

Khi /boot đầy, apt báo lỗi và không cấu hình được package. Xem kernel đang chạy, xác định linux-image có thể gỡ an toàn rồi giải phóng dung lượng.

Vì sao apt ngừng hoạt động khi /boot đầy các kernel cũ

Trên Ubuntu, mỗi lần cập nhật kernel sẽ ghi một bộ file mới vào /boot và giữ lại các file của phiên bản trước. Vì vậy, phân vùng /boot có dung lượng nhỏ sẽ bị đầy và apt không thể hoàn tất quá trình cài đặt. Cách sửa gồm 2 bước. Xác định package nào trên máy là kernel và kernel nào đang được boot, sau đó dùng apt autoremove --purge để gỡ các package còn lại.

Thứ tự thực hiện rất quan trọng. Không được gỡ package của kernel đang chạy. Máy có thể đã ở trạng thái mà apt hoàn toàn không chạy được. Hãy chẩn đoán trước.

Lỗi thực tế biểu hiện như thế nào

Một phiên bản kernel cài 2 file lớn vào /boot: kernel đã nén (vmlinuz-<version>) và initramfs (initial RAM filesystem, initrd.img-<version>, archive nhỏ mà kernel giải nén trước khi mount root thực). Initramfs được build ngay trên máy của bạn trong lúc cài đặt. Vì vậy, quá trình cài cần dung lượng trống, không chỉ cần băng thông tải xuống. Khi không còn đủ chỗ, quá trình build thất bại và kéo theo package cũng thất bại.

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

Chuỗi phiên bản sẽ là phiên bản của bạn. Tên compressor lấy từ COMPRESS= trong /etc/initramfs-tools/initramfs.conf. Vì vậy, một image mới có thể đặt tên là zstd, trong khi image cũ có tên gzip. Hai dòng xác định lỗi này là No space left on device và dòng dpkg: error processing package ngay bên dưới.

Sau đó, package ở trạng thái half-configured. Mỗi lần chạy apt tiếp theo đều cố configure package lại, thất bại theo cùng cách và kết thúc bằng E: Sub-process /usr/bin/dpkg returned an error code (1). Đây là điểm quan trọng ngoài vấn đề dung lượng đĩa: unattended-upgrades chạy theo timer, gặp lại cùng lỗi rồi dừng. Server vẫn có vẻ hoạt động bình thường nhưng âm thầm ngừng áp dụng các bản vá bảo mật. Điều này cũng khiến mọi lần cài đặt không liên quan đều thất bại với cùng dòng lỗi đó. Lỗi bị quy cho thứ bạn đang thêm vào lúc ấy. Vì vậy, một lần cài Tailscale thất bại trên Ubuntu nên được đọc trước hết như một lỗi apt. Nếu apt update thất bại trước khi đến bước này, đó là vấn đề riêng, thường là mục bị trùng sau khi chuyển đổi sources sang deb822.

Kiểm tra xem /boot có phải là phân vùng riêng hay không

Trước khi xóa bất kỳ thứ gì, hãy xác định chính xác bạn đang giải phóng dung lượng ở đâu.

findmnt /boot
findmnt -T /boot
df -h /boot /

Lệnh đầu tiên chỉ in một dòng nếu /boot là mount point riêng. Lệnh thứ hai luôn in kết quả và cho biết filesystem thực sự chứa /boot. Nếu cả hai lệnh đều cho biết cùng filesystem với /, thì /boot chỉ là một thư mục trên root filesystem và không thể tự đầy riêng: root filesystem của bạn đã đầy, còn kernel cũ chỉ là một trong nhiều nguyên nhân. Trong trường hợp đó, sudo apt clean sẽ xóa các file .deb đã tải xuống bên dưới /var/cache/apt/archives và giải phóng thêm dung lượng. Trên máy có phân vùng /boot thực sự, apt clean hoàn toàn không giải phóng dung lượng trên phân vùng đó, vì cache nằm trên filesystem khác.

Bây giờ hãy lấy con số bạn sẽ dùng để đối chiếu.

df -h /boot
ls -lh /boot/vmlinuz-$(uname -r) /boot/initrd.img-$(uname -r)

So sánh cột Avail với kích thước của hai file đó. initrd là file lớn hơn. Lần cập nhật kernel tiếp theo cần thêm dung lượng cho một cặp file có kích thước xấp xỉ như vậy. Vì vậy, nếu Avail nhỏ hơn initrd hiện tại, lần cập nhật tiếp theo chắc chắn sẽ fail.

Tìm kernel đang chạy

uname -r
cat /var/run/reboot-required.pkgs

uname -r in chuỗi release của kernel hiện đang được nạp trong bộ nhớ. Hãy sao chép chuỗi này ra một nơi khác. Đây là phiên bản bạn tuyệt đối không được xóa.

File thứ hai chỉ tồn tại khi một package yêu cầu reboot. Dòng linux-image trong file này nghĩa là trên disk đã có kernel mới hơn nhưng chưa được sử dụng, vì máy chưa reboot kể từ khi kernel đó được cài đặt. Nếu có thể, hãy reboot trước khi dọn dẹp. apt bảo vệ kernel đang chạy và kernel mới nhất. Vì vậy, nếu dọn dẹp khi đang chạy kernel cũ, bạn sẽ giữ lại thừa một phiên bản kernel bị pin.

Liệt kê các package kernel và đọc trạng thái của chúng

dpkg --list | grep -E 'linux-(image|modules|headers|tools)' | awk '{print $1, $2}'

Trường đầu tiên là mã trạng thái của dpkg. ii nghĩa là package đã được cài đặt và cấu hình. iF nghĩa là package đã được cài đặt nhưng mới cấu hình một phần. Đây chính xác là trạng thái mà lần nâng cấp bị lỗi ở trên để lại. rc nghĩa là package đã bị gỡ nhưng cấu hình vẫn còn trên đĩa. Trạng thái này không chiếm dung lượng trong /boot và có thể purge an toàn.

Trường thứ hai cho biết loại package. Tên có version bên trong, chẳng hạn linux-image-6.8.0-64-generic, là một kernel cụ thể. Tên không có version, chẳng hạn linux-image-generic, linux-headers-generic hoặc linux-generic, là meta package. Nó không chứa kernel. Nhiệm vụ duy nhất của nó là phụ thuộc vào kernel có version mới nhất để apt upgrade kéo các kernel mới vào. Gỡ một meta package sẽ khiến máy không còn nhận các bản cập nhật kernel, và sau đó không có cảnh báo nào cho bạn.

Các nhóm được chia như sau. linux-image-* chứa kernel đã nén trong /boot. linux-modules-*linux-modules-extra-* chứa driver trong /lib/modules. linux-headers-* chứa build header trong /usr/src. Vì vậy, purge các header sẽ giải phóng dung lượng trên root filesystem, không phải dung lượng trong /boot. Nếu vấn đề của bạn là phân vùng /boot bị đầy, hãy tìm các image package.

ls -1 /boot/vmlinuz-*
ls -1 /lib/modules/

Hai danh sách này phải khớp với nhau và khớp với output của dpkg --list. Một thư mục trong /lib/modules không có package tương ứng đang được cài đặt là phần còn sót lại do ai đó xóa file thủ công.

Cách apt quyết định kernel nào cần giữ lại

apt autoremove sẽ không gỡ kernel mà nó xem là được bảo vệ. Tập kernel được bảo vệ bao gồm kernel đang chạy. Chính sách giữ lại đã thay đổi giữa các bản phát hành Ubuntu, vì vậy hãy đọc chính sách trên chính máy của bạn thay vì tin vào một con số được ghi sẵn ở đâu đó.

apt-config dump | grep -i -e neverautoremove -e versionedkernel
ls -l /etc/apt/apt.conf.d/01autoremove /etc/apt/apt.conf.d/01autoremove-kernels

APT::NeverAutoRemove là danh sách các mẫu tên package mà apt autoremove từ chối xử lý. APT::VersionedKernelPackages là danh sách các tiền tố tên mà apt trước hết dùng để nhận diện các package kernel có phiên bản. Trên những bản phát hành tạo ra /etc/apt/apt.conf.d/01autoremove-kernels, file đó được /etc/kernel/postinst.d/apt-auto-removal ghi lại mỗi khi cài một package kernel. Vì vậy, chỉnh sửa file này thủ công không có tác dụng: lần cài kernel tiếp theo sẽ ghi đè thay đổi của bạn. Trên những bản phát hành không có file này, apt áp dụng cùng cơ chế bảo vệ ở bên trong. Dù theo cách nào, apt-config dump vẫn hiển thị các quy tắc đang có hiệu lực trên máy của bạn. Kết quả đó là câu trả lời chính xác cho bản phát hành bạn đang dùng.

Dọn dẹp an toàn để chạy

sudo apt update
sudo apt autoremove --purge --dry-run

--dry-run không thay đổi dữ liệu trên disk và in chính xác danh sách những gì lệnh chạy thật sẽ xóa. Hãy đọc danh sách này. Có hai trường hợp bạn phải dừng lại. Một meta package như linux-generic hoặc linux-image-generic xuất hiện trong danh sách gỡ cài đặt có nghĩa là có thành phần nào đó đã đánh dấu nó là tự động cài đặt. Gỡ nó sẽ khiến kernel không còn được cập nhật. Chuỗi từ uname -r xuất hiện trong danh sách gỡ cài đặt có nghĩa là kernel đang chạy không được bảo vệ. Trường hợp này không nên xảy ra. Bạn phải điều tra trước khi tiếp tục.

Nếu danh sách đúng, hãy chạy lệnh thật.

sudo apt autoremove --purge
df -h /boot

Phần --purge cũng xóa cấu hình còn sót lại cùng với package. Nó chỉ giải phóng thêm một ít disk space, nhưng giữ cho dpkg --list không tích lũy các dòng rc, nhờ đó lần audit tiếp theo dễ đọc hơn.

Sau đó xác nhận boot menu đã được rebuild. Việc gỡ một kernel package sẽ tự chạy update-grub, vì vậy menu chỉ nên tham chiếu đến những file vẫn còn tồn tại.

sudo grep -o 'vmlinuz-[^ ]*' /boot/grub/grub.cfg | sort -u
ls -1 /boot/vmlinuz-*

Mọi version trong output đầu tiên phải xuất hiện trong output thứ hai. Một menu entry trỏ đến file đã bị xóa có thể khiến server đang hoạt động dừng tại GRUB prompt. Đây là một nguyên nhân khiến VPS không boot được sau khi cập nhật kernel, và xử lý từ rescue console khó hơn nhiều so với việc phòng tránh ngay từ đầu.

Vì sao apt autoremove đôi khi không xóa gì

apt autoremove chỉ xóa các package được đánh dấu là tự động, tức là các package được cài làm dependency cho một package khác. Kernel do bạn tự cài bằng apt install linux-image-6.8.0-40-generic được đánh dấu là thủ công, nên autoremove sẽ không bao giờ xóa kernel đó, dù kernel đã cũ đến đâu.

apt-mark showmanual | grep -E '^linux-'

Mọi kernel có phiên bản xuất hiện trong kết quả đó đều không bị autoremove xét đến. Hãy đánh dấu lại chúng bằng cách dùng chuỗi phiên bản trong danh sách của chính bạn:

sudo apt-mark auto linux-image-6.8.0-40-generic linux-modules-6.8.0-40-generic
sudo apt autoremove --purge --dry-run

Giữ các meta package ở trạng thái thủ công. Chúng phải được đánh dấu là thủ công vì đó là các package bạn đã yêu cầu cài.

Xóa có chủ đích một kernel được chỉ định

Đôi khi bạn muốn xóa ngay một phiên bản cụ thể thay vì chờ đến khi policy cho phép. Chỉ định image package và để apt xử lý phần còn lại.

sudo apt purge linux-image-6.8.0-40-generic

apt in danh sách các package sẽ bị xóa trước khi thực hiện, vì linux-modules-extra-* phụ thuộc vào image package và phải được xóa trong cùng một transaction. Danh sách này là bước kiểm tra an toàn thực tế của bạn. Tại đây, bạn có thể phát hiện meta package bị kéo theo cùng với phiên bản bạn muốn xóa. Trả lời n nếu danh sách có bất kỳ mục nào không mong muốn. Sau đó chạy sudo apt autoremove --purge để thu thập các module package và header package không còn lý do tồn tại.

Vì sao không bao giờ xóa kernel đang chạy

Kernel đã được nạp vào memory vẫn tiếp tục chạy sau khi các file của nó bị xóa, nên ban đầu không có gì có vẻ bị hỏng. Những phần bị hỏng là mọi thứ mà kernel chưa nạp. Purge linux-modules-$(uname -r) sẽ xóa /lib/modules/$(uname -r)/, nên lần nạp module tiếp theo sẽ fail:

modprobe: FATAL: Module nf_tables not found in directory /lib/modules/6.8.0-64-generic

Từ thời điểm đó, việc reload firewall sẽ fail, cũng như việc mount một filesystem type mà kernel này chưa từng xử lý kể từ khi boot. Trong khi đó, /boot/vmlinuz-$(uname -r) đã biến mất, nên boot menu không còn cung cấp kernel đang chạy, và lần reboot tiếp theo sẽ khởi động vào một kernel khác. Máy vẫn tiếp tục phục vụ network traffic nhưng đã không thể boot. Mỗi lần hãy kiểm tra uname -r với danh sách sẽ bị xóa.

Khi /boot quá đầy khiến apt hoàn toàn không chạy được

Đây là tình trạng khiến nhiều người tìm đến trang này. apt autoremove cần dpkg hoàn tất cấu hình package kernel đang ở trạng thái cấu hình dở dang trước, và bước đó sẽ rebuild initramfs. Việc này cần dung lượng trong /boot, nhưng phân vùng đó không còn chỗ. Hãy phá vòng lặp này thủ công, chỉ một lần.

uname -r
ls -1 /boot/initrd.img-*

Chọn một initrd có version không phải chuỗi mà uname -r cung cấp, rồi xóa đúng file đó.

sudo rm /boot/initrd.img-6.8.0-40-generic
sudo apt --fix-broken install
sudo apt autoremove --purge
sudo update-grub

Mỗi dòng đều có lý do. rm là một ngoại lệ có chủ ý, khiến dpkg vẫn tin rằng một file tồn tại dù file đó không còn. apt --fix-broken install hoàn tất cấu hình đã fail sau khi đã có chỗ cho initramfs. Sau đó autoremove --purge xóa package chứa file bạn đã xóa cùng với các version cũ khác, đưa dpkg trở lại khớp với nội dung thực tế trên disk. update-grub rebuild menu từ những file thực sự tồn tại. Không reboot giữa rmupdate-grub, vì trong khoảng thời gian đó menu vẫn có thể trỏ đến file bạn vừa xóa. Nếu dpkg báo rằng nó bị gián đoạn, sudo dpkg --configure -a sẽ thực hiện cùng thao tác sửa lỗi như apt --fix-broken install.

Công việc tương tự trên các hệ thống dnf

Nếu VPS của bạn chạy Fedora hoặc một bản rebuild của RHEL như Rocky Linux, cơ chế này ngược lại. Debian và Ubuntu bảo vệ kernel bằng các quy tắc autoremove của apt và để bạn hoặc unattended-upgrades thực hiện việc dọn dẹp, còn dnf áp dụng một số lượng gọi là installonly_limit và tự động xóa kernel cũ nhất ngay khi một lần cài đặt mới khiến số lượng vượt quá giới hạn này. Đọc giá trị hiện tại bằng grep installonly_limit /etc/dnf/dnf.confman 5 dnf.conf, rồi xóa các kernel tồn đọng bằng sudo dnf remove --oldinstallonly. Kernel đang chạy cũng được bảo vệ trên các hệ thống này. Để xem bảng đối chiếu rộng hơn giữa hai package manager, hãy xem các lệnh tương đương giữa dnf và apt.

Ngăn lỗi tái diễn

Dọn dẹp dựa vào việc bạn nhớ thực hiện sẽ sớm hoặc muộn bị bỏ sót, vì vậy hãy đưa việc này vào thành phần cài đặt kernel. Mở /etc/apt/apt.conf.d/50unattended-upgrades và tìm các khóa sau. File được cung cấp sẵn đã có chúng dưới dạng các dòng chú thích:

Unattended-Upgrade::Remove-Unused-Kernel-Packages "true";
Unattended-Upgrade::Remove-Unused-Dependencies "true";

Bỏ chú thích các dòng này thay vì thêm một bản sao khác vào cuối file. Trong cấu hình apt, phép gán cuối cùng của một khóa sẽ được áp dụng. Vì vậy, các khóa trùng nhau khiến file tự mâu thuẫn và che khuất giá trị thực sự đang được dùng. Kiểm tra kết quả parser đã đọc được và theo dõi một lần chạy không thay đổi gì:

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

Log là bằng chứng. Log ghi lại từng lần chạy, vì vậy một lần nâng cấp thất bại do thiếu dung lượng sẽ xuất hiện ở đó từ lâu trước khi có người nhận ra máy chủ chưa được cập nhật bản vá. Phần còn lại của cấu hình này được trình bày trong cập nhật bảo mật tự động trên Ubuntu.

Trước khi kernel tiếp theo được cài đặt, có một con số cần kiểm tra. Đây cũng là cặp lệnh được dùng ở đầu hướng dẫn này:

df -h /boot
ls -lh /boot/initrd.img-$(uname -r)

Nếu Avail không lớn hơn file đó một cách đủ an toàn, kernel tiếp theo sẽ thất bại đúng như mô tả ở trên. Vì vậy, hãy xử lý ngay thay vì chờ đến lúc nâng cấp. Bạn nên dành một phút để kiểm tra này cùng với các kiểm tra tình trạng disk trên VPS khác. Việc này đặc biệt quan trọng ngay trước khi nâng cấp release, vì chuyển Ubuntu 24.04 lên 26.04 sẽ cài kernel mới ngay từ đầu quy trình và do-release-upgrade sẽ từ chối tiếp tục khi /boot không còn đủ dung lượng.

FAQ

Vì sao Ubuntu giữ lại kernel cũ thay vì xóa chúng?

Vì nếu một kernel không khởi động được, bạn sẽ không còn phiên bản nào khác để chọn. Giữ lại phiên bản trước cho phép khôi phục sau một lần cập nhật lỗi từ menu GRUB, thay vì phải dùng rescue console của nhà cung cấp. Vì vậy, apt bảo vệ một nhóm package kernel khỏi việc tự động bị xóa, luôn bao gồm kernel đang chạy. Chạy apt-config dump | grep -i neverautoremove để xem chính xác các pattern mà bản release của bạn đang bảo vệ, vì chính sách này đã thay đổi giữa các bản release.

Chạy apt autoremove --purge trên production server có an toàn không?

Có, với điều kiện bạn đọc kết quả dry run trước. Chạy sudo apt autoremove --purge --dry-run. Lệnh này không ghi thay đổi nào. Kiểm tra danh sách được in ra. Dừng lại nếu danh sách có meta package như linux-generic hoặc linux-image-generic, vì xóa một trong các package này sẽ chặn mọi lần cập nhật kernel sau đó. Cũng dừng lại nếu danh sách có chuỗi phiên bản mà uname -r in ra. Nếu không có hai trường hợp này, các package bị xóa là kernel cũ và dependency mồ côi.

apt autoremove không xóa gì nhưng /boot vẫn đầy. Làm gì tiếp theo?

Các kernel cũ gần như chắc chắn đang được đánh dấu là manual, còn autoremove chỉ xử lý các package được đánh dấu là automatic. Chạy apt-mark showmanual | grep -E '^linux-'. Bất kỳ kernel có phiên bản nào được liệt kê ở đó đều đã được cài thủ công vào một thời điểm nào đó. Đánh dấu nó là automatic bằng sudo apt-mark auto linux-image-<version> rồi chạy lại dry run, hoặc purge trực tiếp phiên bản đó bằng sudo apt purge linux-image-<version>.

Tôi có thể tự xóa file trong /boot không?

Chỉ nên làm một lần có chủ đích, khi /boot đầy đến mức apt không thể configure package kernel đang bị lỗi. Xóa một file initrd.img-<version> duy nhất có phiên bản không phải là kết quả của uname -r, sau đó chạy ngay sudo apt --fix-broken install, sudo apt autoremove --purgesudo update-grub. Xóa file mà không thực hiện các bước tiếp theo sẽ khiến dpkg vẫn ghi nhận những package có file đã bị xóa, đồng thời để lại các mục trong menu GRUB trỏ đến file không tồn tại. Khi đó máy sẽ fail ở lần reboot tiếp theo, thay vì fail ngay lúc bạn mắc lỗi.