Ubuntu系统在长期使用过程中,每次内核更新都会在boot分区保留旧版本的内核镜像文件(vmlinuz)、初始化内存盘(initrd.img)以及System.map等文件,这些文件通常每个版本占用200MB到300MB左右。如果你从不手动清理,boot分区很快就会被塞满,导致系统无法正常启动,甚至在更新时直接报错"No space left on device"。最直接有效的解决办法就是:定期删除不再使用的旧内核,保留当前正在运行的内核以及至少一个备用内核,释放boot分区的宝贵空间。下面我会从原理到实操,把这件事讲透。

为什么boot分区会被旧内核占满?

Ubuntu默认的boot分区大小通常只有500MB到1GB,这个空间对于存放内核文件来说其实非常紧张。每次执行apt upgrade或者系统自动更新时,新内核会被安装到boot分区,但旧内核并不会自动删除。系统设计上保留旧内核是为了防止新内核出现兼容性问题时可以回退,这本身是一个安全机制。但问题在于,Ubuntu不会主动帮你清理,它只会一直堆积。一般来说,保留3到4个内核版本就足够安全了,超过这个数量基本就是浪费空间。

你可以用以下命令查看当前安装了哪些内核:

dpkg --list | grep linux-image

输出结果会列出所有已安装的内核镜像包,比如linux-image-5.15.0-91-generic、linux-image-5.15.0-92-generic等等。每一行对应一个内核版本,你可以直观看到有多少个版本堆在那里。

如何确认当前正在使用的内核版本?

在清理之前,你必须先知道当前系统正在运行哪个内核,否则误删了正在用的内核,重启后系统就起不来了。查看当前内核版本的命令非常简单:

uname -r

输出类似5.15.0-91-generic这样的版本号,这就是你当前运行的内核。另外还可以用这个命令查看所有已安装内核中哪些是正在使用的:

dpkg --list | grep linux-image | grep ^ii

其中带有"generic"或者"lowlatency"等后缀的就是实际的内核镜像包。记住当前版本号,后续清理时要把它排除在外。

方法一:使用apt命令自动清理旧内核(推荐)

这是最安全、最简单的方法,适合绝大多数用户。Ubuntu提供了一个专门用于清理旧内核的命令:

sudo apt autoremove --purge

这个命令会自动识别并删除那些不再被任何包依赖的旧内核镜像和相关文件。它会保留当前正在使用的内核,同时清理掉多余的版本。执行之前系统会列出将要删除的包,你可以仔细看一遍确认无误后再输入Y继续。

如果你想更精确地只清理内核相关的包,可以用:

sudo apt autoremove --purge 'linux-image-*'

但要注意,这种写法可能会过于激进,建议还是用第一种不带通配符的方式更稳妥。执行完之后,用df -h查看boot分区的使用情况,你会发现空间明显释放了。

方法二:手动指定删除特定内核版本

如果你想精确控制删除哪些内核,可以手动指定版本号。比如你当前用的是5.15.0-91-generic,想删除5.15.0-88和5.15.0-89这两个旧版本,操作如下:

sudo apt purge linux-image-5.15.0-88-generic linux-image-5.15.0-89-generic
sudo apt purge linux-headers-5.15.0-88-generic linux-headers-5.15.0-89-generic

注意,除了linux-image包,对应的linux-headers头文件包也要一起删除,否则空间释放不彻底。删除完成后,建议更新一下引导配置:

sudo update-grub

这个命令会重新生成grub引导菜单,把已删除的内核从启动选项中移除,避免启动时还显示已经不存在的内核条目。

方法三:使用purge-old-kernels脚本(高级用户)

Ubuntu其实自带了一个专门的脚本叫purge-old-kernels,它比apt autoremove更智能,会自动保留最近的两个内核(当前运行的+一个备用),其余全部清理。使用方法:

sudo purge-old-kernels --keep 2

其中--keep 2表示保留2个内核,你也可以改成--keep 3保留3个。这个脚本在/usr/lib/linux-tools-common/目录下,是系统自带的工具,不需要额外安装。它会自动处理image、headers、modules等所有相关包,清理得非常干净。

清理后如何验证boot分区空间和引导状态?

清理完成后,你需要做两件事来确认一切正常。第一,检查空间:

df -h /boot

如果之前使用率在90%以上,清理后应该降到50%以下甚至更低。第二,确认grub引导正常:

sudo update-grub

执行后如果没有报错,说明引导配置更新成功。最后重启一次系统验证:

sudo reboot

重启后再次用uname -r确认内核版本正常,就说明清理操作完全成功,没有任何副作用。

如何设置定期自动清理?避免手动操作遗忘

作为运维人员,最怕的就是忘记清理导致boot分区再次爆满。最好的办法是设置定时任务,让系统自动帮你干这件事。编辑crontab:

sudo crontab -e

在文件末尾添加一行:

0 3 * * 1 apt autoremove --purge -y >> /var/log/kernel-cleanup.log 2>&1

这条cron的含义是:每周一凌晨3点自动执行内核清理,并把执行日志写入/var/log/kernel-cleanup.log。你可以根据自己的更新频率调整时间,比如如果系统更新频繁,可以改成每周执行两次。这样即使你完全不管,系统也会自动保持boot分区的健康状态。

boot分区空间不足时的紧急处理方案

如果你已经遇到了boot分区100%满、系统无法更新甚至无法启动的紧急情况,需要先手动删除最旧的内核来腾出空间。步骤如下:先进入恢复模式或者用Live USB启动,挂载原系统的boot分区,然后手动删除旧内核文件。或者更简单的方式,直接在终端执行:

sudo apt purge $(dpkg -l | grep 'linux-image' | grep '^ii' | awk '{print $2}' | grep -v $(uname -r) | head -n -2)

这条命令的逻辑是:列出所有已安装的linux-image包,排除当前运行的内核,保留最后两个(也就是最新的两个),其余全部删除。head -n -2的意思是去掉最后两行,即保留最新的两个版本。这是一个应急手段,平时不建议用,但关键时刻能救命。

扩展建议:调整boot分区大小或者迁移内核存放位置

如果你的服务器长期运行且内核更新频繁,500MB的boot分区确实不够用。有两个思路:一是在安装系统时就把boot分区设大一些,比如2GB甚至4GB;二是修改grub配置或者使用LVM,把内核文件放到其他分区。不过这些操作涉及分区调整,风险较高,建议在有备份的情况下操作。对于大多数场景,定期清理旧内核就完全够用了,没必要折腾分区结构。

总结:定期清理旧内核是Ubuntu运维的基本功

Ubuntu不会自动帮你清理旧内核,这是系统设计的取舍——安全优先但需要人工维护。作为运维人员,你只需要记住三件事:第一,用apt autoremove --purge定期清理;第二,保留至少两个内核作为回退保障;第三,设置cron定时任务实现自动化。做到这三点,boot分区空间问题就永远不会成为你的困扰。这不是什么高深技术,但确实是很多Ubuntu服务器出故障的隐形原因,值得每一个运维人员重视。