清理/boot分区的最安全方法是什么?

我为/boot分区分配了200 MB的空间。每当我尝试更新内核时,都会收到一个错误消息,基本上是说/boot已满。
我该如何清理/boot并删除/备份旧的内核?

1请查看Ubuntu社区维基 - jarno
如果/boot目录已满,请参考https://askubuntu.com/questions/263363/how-can-i-remove-old-kernels-install-new-ones-when-boot-is-full/1158420#1158420。 - null
8个回答

命令行方法:

首先检查您的内核版本,以免删除正在使用的内核映像,运行以下命令:

uname -r

现在运行这个命令以获取已安装内核的列表:
dpkg --list 'linux-image*' | grep ^ii

删除你不再需要的内核,运行以下命令:
sudo apt-get remove linux-image-VERSION

将“VERSION”替换为您想要删除的内核版本。
在删除旧内核后,您可以运行以下命令来删除不再需要的所有软件包:
sudo apt-get autoremove

最后,你可以运行这个命令来更新grub内核列表:
sudo update-grub

36sudo dpkg --list 'linux-image*' | grep ^ii 这个命令可以更方便地查看已安装的内核。另外,我认为 update-grub 是无害的,但并非必需,因为当您卸载一个内核时,它会自动运行。 - Nelson
11使用 sudo dpkg --list 'linux-image*' | grep ^ii | awk '{print $2}' | sort | egrep "[0-9]-generic" | head -n -3 | tr '\n' ' '; echo "" 获取要与 sudo apt-get remove 一起使用的软件包名称列表。head -n -3 用于保留系统中最近的 3 个内核版本。 - Sithsu
4我的简单一行代码:apt-get remove \dpkg --list 'linux-image*' |grep ^ii | awk '{print $2}'\ | grep -v \uname -r\\`` - gcb
你可以使用awk来执行其中一个grep操作,但是我找不到awk中绕过反引号的方法来执行另一个操作: sudo dpkg --list 'linux-image*'|awk '{ if ($1=="ii") print $2}'|grep -v `uname -r` - flickerfly
32sudo apt-get autoremove 应该足够了(通常会保留最后3个内核)。 - mbx
3对于dpkg --list(或等效地,dpkg -l),你不需要使用sudo - Keith Thompson
10这是一个不错的答案,但我怀疑它在大多数(如果不是全部)情况下都无法工作:问题在于/boot已满,因此apt-get将失败并显示一些错误代码。下面的答案有点“hackier”(我必须承认我不得不鼓起勇气在/boot中发出rm -rf),但这是唯一可能在这种情况下起作用的方法。 - Marco Massenzio
Ubuntu 16.04:按照这组命令操作,一切顺利完成,但是dpkg --list 'linux-image*'仍然列出了我删除的内核,并且它仍然存在于/boot分区中。如果/当我发现问题时,我会更新评论。 - markdsievers
更新.. 在重新启动并再次运行 sudo apt-get autoremove(仅删除相关的头文件)之后,/boot 分区被清空了。有趣的是 dpkg --list 'linux-image*' 仍然列出了我删除的所有内核。 - markdsievers
@mbx在来这里之前就尝试过那个方法,但没有成功。实际上,我在那里安装了七个该死的内核...不过,"sudo apt autoremove --purge" 这个命令在某种程度上解决了问题(它只留下了我的系统中“仅有”的五个内核)。 - Fran Marzoa
@Fran听起来你在进行完整升级之前没有清理 - 除了可能是由于错误导致的情况,我不知道其他忘记已安装内核的原因。 - mbx
我发现在16.04版本中,“update-grub”命令会自动执行 :) - Brendan
我不得不使用这里的说明来使它工作:https://boinst.wordpress.com/2013/05/14/clean-out-ubuntu-boot-partition/ - lucasvw
由于我们显然正在进行awk的代码压缩... awk '{ if ($1=="ii") print $2}' 可以替换为 awk '/^ii/ {print $2}' - Johannes Hoff
initrd.img-4.13.0-26-generic initrd.img-4.15.0-161-generic initrd.img-4.15.0-166-generic initrd.img-4.15.0-167-generic initrd.img-4.8.0-53-generic initrd.img-5.4.0-131-generic initrd.img-5.4.0-132-generic这些文件正常吗?但是dpkg只显示了5.4.0-131和132,我可以安全地手动删除其他的吗? - Tofandel

注意:只有在/boot目录已满100%且无法使用apt清理时才需要执行以下操作

如果apt-get无法正常工作,因为你的/boot目录已满100%,你需要先清理/boot目录。这很可能是由于部分安装的内核升级导致的,这意味着apt基本上完全冻结了,并且会一直告诉你运行apt-get -f install,即使该命令一直失败。

获取内核镜像列表并确定哪些是可以删除的。以下命令将显示已安装的内核,但不包括当前正在运行的内核:sudo dpkg --list 'linux-image*'|awk '{ if ($1=="ii") print $2}'|grep -v `uname -r`。请注意列表中的两个最新版本。你不需要担心正在运行的内核,因为它不在此列表中。你可以通过uname -r来检查。

使用大括号扩展命令来删除/boot目录下与你无关的内核文件,以保持清晰明了。请记得排除当前和最新的两个内核镜像。 例如:sudo rm -rf /boot/*-3.2.0-{23,45,49,51,52,53,54,55}-*。你也可以使用范围语法{80..84}。
运行sudo apt-get -f install来清理apt在部分安装方面出现问题的内容。
如果遇到包含“Internal Error: Could not find image (/boot/vmlinuz-3.2.0-56-generic)”这样一行的错误,请运行命令sudo apt-get purge linux-image-3.2.0-56-generic(根据你的版本进行相应更改)。
最后,运行sudo apt-get autoremove来清除手动清理/boot目录后留下的旧内核镜像包。
建议运行sudo apt-get updatesudo apt-get upgrade来处理可能在等待你发现完整的/boot分区时积压的任何升级。
建议2,查看https://help.ubuntu.com/community/AutomaticSecurityUpdates并考虑在/etc/apt/apt.conf.d/50unattended-upgrades中将Unattended-Upgrade::Remove-Unused-Dependencies设置为true。这相当于在每次安全更新后运行autoremove,以确保清理未使用的内核,但也会删除其他它认为是未使用的内容,从而避免将来出现此问题。

我可以问一下为什么要排除最后两个最新的内核镜像吗? - nightire
3这样我就能在下一次重启之前拥有最新的备份,以及在那之前的一个备份,以防万一出现问题。通常情况下,我有足够的空间,所以多备几个也不会有什么损失,而且满足了我对于在任何情况下都没有足够备份选项的偏执心理。 - flickerfly
很棒的回答!你认为启用Unattended-Upgrade::Remove-Unused-Dependencies是完全安全的吗? - mkataja
2我从未遇到由未经处理的升级引起的问题。我可以想象出一些情况,其中可能会出现问题,主要是在非deb软件包安装中丢失依赖关系。比如你安装了php,然后决定将其卸载并从源代码安装更高版本。这个版本的依赖关系由先前的安装提供,但apt并不知道它们仍然被需要。下次运行自动删除时,这些依赖关系将会消失。如果自动化进行,可能会有点困惑。如果你不在软件仓库之外安装,我认为完全安全。 - flickerfly
我更新了这个命令,以便以更有用的格式列出内核,并自动排除当前正在运行的内核。这样可以加快速度一些。sudo dpkg --list 'linux-image*'|awk '{ if ($1=="ii") print $2}'|grep -v `uname -r` - flickerfly
3在几个vsphere虚拟服务器上看到这种情况(内核自动升级后未被删除),我编写了一个Python脚本来自动化处理。希望能有更多人参与审查。 - EvanK
+EvanK,实现自动化这一点的方式不错。或许可以建议大家在遇到这个问题后,在/etc/apt/apt.conf.d/50unattended-upgrades中设置Unattended-Upgrade::Remove-Unused-Dependencies。我发现这非常有用,但需要一些理智来考虑是否要移除不应该移除的东西。尽管很少发生这种情况。 - flickerfly
awk命令返回当前正在运行的内核,我用uname -r输出进行了交叉验证。 - Chinmaya B
你在末尾是否包含了 grep -v uname -r 的输出结果? - flickerfly
@EvanK 我认为使用 sudo rm 删除旧内核是不必要的。我认为最好使用 sudo dpkg --purge。请参考我对类似问题的回答以获取更多详细信息。 - jarno
2如果你在完全启动时使用dpkg --purge命令,你会得到以下结果:`$ sudo dpkg --purge linux-image-3.13.0-65-generic
dpkg: 依赖问题阻止了对 linux-image-3.13.0-65-generic 的移除: linux-image-extra-3.13.0-65-generic 依赖于 linux-image-3.13.0-65-generic。dpkg: 处理软件包 linux-image-3.13.0-65-generic (--purge) 时出错: 依赖问题 - 无法移除 处理时遇到错误: linux-image-3.13.0-65-generic`
- flickerfly
1清理了/boot之后,apt-get install -f仍然无法正常工作。通过使用df -i命令,我发现由于在/usr/src目录下存储了大量旧内核源代码文件,导致根目录/的inode也不足。 - Kristofer
1这非常有帮助。对我起了作用。 - deepdive
在搜索了将近一个小时后,这是唯一对我有效的解决方案,当时我的/boot分区剩余0字节。 - Brad
1sudo apt-get -f install 将重新安装我刚刚删除的内核,并在磁盘空间不足时崩溃。我使用的是Mint 18。 - Pavel Niedoba

关于此事有相关文档可参考https://help.ubuntu.com/community/RemoveOldKernels

简而言之:使用

sudo apt-get autoremove --purge
# and/or:
sudo purge-old-kernels

可以通过sudo apt install byobu安装purge-old-kernels工具。以下是它的man页描述:

该程序将从系统中删除旧的内核和头文件包,释放磁盘空间。它永远不会删除当前正在运行的内核。默认情况下,它将保留至少最新的2个内核,但用户可以使用--keep参数覆盖该值。

如果你想要一个复制粘贴的解决方案,ReSearchIT Eng建议如下:

sudo apt install -y byobu
sudo purge-old-kernels -y --keep 1
sudo apt-get -y autoremove --purge

3在我的情况下,apt无法工作,因为有一个未完成的内核,并且建议的修复方法是一个进退两难的局面: - James Bowery
我必须先用http://askubuntu.com/a/304388/284313修复损坏的软件包,之后你的解决方案有效。 - James Bowery
3我认为这应该是目前被接受的解决方案。 - Fran Marzoa
3这种方法比接受的答案更安全。我认为apt-get autoremove --purge应该足够了。 - Woodrow Barlow
2或许事情已经改变了。我收到了这个错误信息: E: 在与其他选项组合使用时,不理解命令行选项--keep - Houman


1这是唯一有效的一个……很棒的解决方案。 - John
2最佳答案!这是唯一有效的解决方案;autoremove 太愚蠢了;它在正式删除内核之前会尝试重新安装任何存在未满足依赖关系的内核。我一直在循环中反复耗尽空间。 这个答案就像黄金。 - Lonnie Best
绝对值得点赞 - 谢谢 @Amos - CRTLBREAK

我发现放弃小分区并将/boot移动到根目录要容易得多。这样还可以预防未来的空间不足问题。
首先将boot分区中的数据移动到根目录(以sudo -s身份运行):
cp -a /boot /boot2
umount /boot
rmdir /boot
mv /boot2 /boot

在/etc/fstab中删除(或注释掉)/boot条目。
vim /etc/fstab

更新 grub 并确保一切正确无误。
update-grub

apt 现在应该能够顺利升级了。

这会留下一个未使用的 200mb 分区(如果你觉得值得的话,可以用来做其他事情)。


8这是一个好主意,但如果你想要对根分区进行全盘加密的话,这个方法就不适用了。 - Paŭlo Ebermann
是的,有些情况下/boot应该是一个独立的分区。另一个例子是以前Grub无法从LVM分区加载。 - Bastion

sudo apt-get autoremove

这将删除除最后2个内核之外的所有内核。在Ubuntu 16.04 LTS上进行了测试,当/boot的容量达到100%并且apt-get upgrade无法完成最新的内核升级时。内核自动删除是迭代的,所以如果你有多个内核,它们将逐个被删除。所以请耐心等待。


为什么要手动操作,当你可以用工具来完成呢?你知道在30秒内你又会需要它,因为现在推送一个新的内核更新需要30秒的时间 =P
我建议使用这个工具,bootnukem
git clone https://github.com/erichs/bootnukem.git
cd bootnukem
sudo ./install.sh

然后

sudo bootnukem --dry-run

确认安全后,请移除--dry-run