如何删除旧的内核版本以清理启动菜单?

每次我安装一个新的Linux内核,它都会留在grub_config中,导致启动菜单变得越来越长。
我知道我可以手动搜索已安装的软件包并将其删除。
Ubuntu是否提供更简便的方法来清理它们或防止它们显示在启动列表中?

如果你想要在菜单中摆脱“恢复”选项,除了删除旧的内核之外,还应该取消注释/etc/default/grub中的这行代码:#GRUB_DISABLE_LINUX_RECOVERY="true"。 - poolie
最近的Ubuntu版本将内核隐藏在Grub的子菜单中,因此不会那么显眼。然而,如果你有一个独立的小型/boot分区,删除多余的内核以节省空间可能是个好主意。 - jarno
10有一个叫做purge-old-kernels的Ubuntu命令可以完成这个任务。更多信息请参考我的回答 - jarno
31在Ubuntu 14.04+上,sudo apt-get autoremove应该能解决问题。 - hobs
1旧内核的积累是一个错误,但已经在修复中:https://bugs.launchpad.net/bugs/1357093。当修复发布时,旧内核将默认自动删除。 - user535733
1@hobs 如果内核不是通过软件更新器自动安装的话,在Ubuntu Studio 14.04中,这个命令对我来说没有起作用。 - jarno
我找不到任何答案可以帮助在将Ubuntu升级到新版本后删除先前版本的内核,即使有一个关于此问题的具体问题被标记为重复这里。还请参阅相关的错误报告 - jarno
https://help.ubuntu.com/community/RemoveOldKernels - dskrvk
@hobs,你能把这个评论转化为一个回答吗? - 030
阅读此文的人也应该阅读https://stackoverflow.com/questions/653096/how-to-free-inode-usage。你可能会遇到这样的情况,需要通过删除/usr/src/下的旧内核源代码来释放inode。如果使用df -h检查时发现磁盘空间足够,但inode使用率达到100%,那么你绝对需要阅读上述链接。 - cwhsu
2我一直回到这个页面... @hobs的评论只在您的内核是自动安装的情况下有效 - 但是,您可以通过按照https://help.ubuntu.com/community/RemoveOldKernels上的apt-mark建议来执行sudo apt-get autoremove --purge这个答案 - earcam
如果/boot分区已满,请查看https://askubuntu.com/questions/263363/how-can-i-remove-old-kernels-install-new-ones-when-boot-is-full/1158420#1158420。 - null
有用的要点 - https://gist.github.com/ipbastola/2760cfc28be62a5ee10036851c654600 - slm
40个回答

16.04及更高版本的Ubuntu
sudo apt autoremove

这个命令会删除那些为了解决依赖关系而自动安装的软件包,但现在不再有依赖关系。这包括旧版本的linux-headers-*linux-image-*。(它还会智能地处理此过程,保留一个备用版本的内核!)
Ubuntu 11.10及更新版本
GRUB2及其显示所有内核的功能
最新版本的Ubuntu中安装的Grub2会自动显示最新的内核,并隐藏您可能安装的旧内核。

GNU GRUB

如果您没有看到您的grub - 那么请记住在启动时按下Shift键。
正如您所见,只显示最新的内核。
如果您选择显示的选项(按Enter键),那么所有旧的内核都将变得可见并可用于启动。

GNU GRUB Previous versions

如何永久删除旧内核

首先使用最新可用的内核启动。

有多种方法可以删除旧内核。个人而言,我不会碰计算机清洁工,因为众所周知它的建议会破坏你的计算机。

Synaptic

另一种选择是Synapticsudo apt install synaptic

搜索linux-image,右键点击一个内核,选择完全删除,最后点击应用按钮来删除该内核。

Synaptic Package Manager

重复搜索,但这次是为了linux-header - 您可以删除先前选择的内核映像的相关头文件。 Synaptic不会尝试验证您要删除的内容...您可能会意外删除最新的内核 - 或者甚至通过此工具删除所有内核,导致您的Ubuntu无法启动!。
记得检查你正在使用的内核类型:
uname -r

结果会类似于:

Terminal <uname -r>

记住结果和编号 - 确保不要删除相应的图像或标题。
推荐
我的建议是至少保留两个或者最好三个内核,其中包括最新的内核。推荐的原因是,如果由于某种原因无法使用最新的内核或引入了退化的功能(如破损的无线网络),您将至少有一个或两个其他内核可供启动。

3使用Synaptic删除旧的“linux-image*”软件包,在10.04上也可以很好地工作。(我提到这一点是因为标题暗示它可能只适用于11.10及更高版本) - mivk
4apt-get命令行的末尾加上-y开关是必要的,否则apt-get会询问是否确认操作,由于输入是通过管道传递的,它会直接中止操作。因此,命令应该以| xargs sudo apt-get purge -y结尾。 - Josh
我添加了另一种方法,不使用xargs命令,在删除内核之前会在控制台上询问确认。 - rubo77
1如果你建议至少保留两个内核,你可以编写一个脚本来实现这一点;)(我只是在寻找一个能够做到这一点的脚本,但似乎我得自己写了) - törzsmókus
1我尝试了使用Ubuntu Tweak这种方法,因为它是最合适的(即傻瓜式操作)。效果很好。 - Bobble
39删除大约20个旧版本的linux-imagelinux-headers,为我的机器释放了4.5GB的空间。 - Andrew Mao
这样做清理了大约4.5GB的数据。+1!! - triplethreat78
19这种方法很有效,但是每次删除内核都会过度重新生成grub.cfg,这需要时间。有没有办法在批量删除时禁用它,然后再重新生成一次呢? - spacediver
你可能希望在你的机器上保留较新的内核-你可以检查dpkg -l 'linux-*' | sed '/^ii/!d;/'"$(uname -r | sed "s/\(.*\)-\([^0-9]\+\)/\1/")"'/d;s/^[^ ]* [^ ]* \([^ ]*\).*/\1/;/[0-9]/!d',确保它不包含任何比uname -r显示的内核更新的内核。 - user35581
1注意,删除内核的命令也会在我的机器上删除这个包 - linux-libc-dev - 这是不希望的行为。你可以使用 dpkg -l 'linux-image-*' ... 来避免这种情况。 - Dimitar
16我支持 @spacediver 的问题 - 当您有38个不必要的内核时,这是一个非常缓慢的过程,因为每当卸载一个内核时,它会在生成新的grub.cfg时通过所有剩余的内核。 这就是所谓的N ^ 2操作 - 它处理约(38 ^ 2/2)= 722次内核,并且非常缓慢。 Ubuntu肯定可以想出更好的解决办法.... - nealmcb
1列出旧镜像的简化命令:dpkg -l 'linux-image-*' | awk '/^ii/ { print $2 }' | grep -iv $(uname -r) - Hauleth
这个解决方案对于没有运行X的无头机器不会有任何帮助。 - 0xC0000022L
@Łukaszniemier,你的脚本可能会列出一个名为linux-image$(uname -r | sed -r 's/^[0-9.]+-[^-]+//')的软件包,它依赖于最新可用的内核镜像,所以你可能不想删除它。 - jarno
@Dimitar,是的,脚本有问题。但是你改变脚本的方式会导致它无法删除所需的头部包。 - jarno
我写了一个脚本,旨在保留给定数量的内核并删除多余的内核:链接 - jarno
@ŁukaszNiemier,你可能想看一下我的答案的结尾。 - jarno
有没有终端推荐? - bryan
@Lynn - 这是一个社区维基,任何人都可以编辑和添加更多信息。 - fossfreedom
@Lynn apt-get autoremove一直存在,至少从10.04版本开始。为什么要将其标记为16.04及以上版本呢? - muru
@muru 我看到另一个答案将其标记为16.04+,并相信它有理由这样做。(也许在旧版本中,它对内核版本的删除不够智能?我不知道。我只是推广在16.04上对我有效的解决方案) - Lynn
3autoremoveеѓєжИСжЭ•иѓіжЧ†ж≥ХеИ†йЩ§жЧІзЪДLinuxйХЬеГПгАВ - Ziemo
我尝试使用 Synaptic 删除 Linux 镜像,但出现了以下错误:已安装的 linux-image-4.15.0-74-generic 软件包的后删除脚本子进程返回错误退出状态 1 dpkg:错误太多,停止处理 处理过程中遇到了错误: linux-image-4.15.0-74-generic 由于出现了太多错误,处理过程被中断。 E:子进程 /usr/bin/dpkg 返回错误代码(1)``` 请帮忙,我最近升级到了 Ubuntu 20.04,现在无法下载任何东西。 - nkhl
我只是想补充一下,随着时间的推移,删除内核导致我的/lib/modules文件夹中积累了很多残留数据。为了清除已删除的内核数据,可以使用以下命令:sudo apt purge $(dpkg -l | grep '^rc linux-image' | awk '{print $2}') - gcode

首先,重新启动您的系统以确保它正在使用最新的内核。然后打开终端并检查您当前的内核:
uname -r 

请勿删除此内核!

接下来,输入下面的命令以查看/列出系统中安装的所有内核。

dpkg --list 'linux-image-*'

找出所有低于当前内核版本的内核。当你知道要删除哪个内核时,继续以下步骤进行删除。运行下面的命令来删除你选择的内核。
sudo apt-get purge linux-image-x.x.x-x-generic 

最后,运行以下命令来更新grub2。
sudo update-grub2 

重新启动您的系统。

35在10.04和12.04版本中进行此操作时,我发现在清除过程中会自动运行update-grub命令。 - aidan
94bash的花括号扩展可以用于,例如sudo apt-get purge linux-image-3.2.0-3{0..5}-generic(删除30、31、...、35)。 - ajo
这个答案与其他答案不同的显而易见之处在于“找到所有比你当前内核更低的内核。”这正是我所需要的信息。 - Ziggy
13无需在此之后重新启动系统。事实上,在执行这些步骤之前,应该重新启动系统,以确保您正在使用最新的内核版本,您可能刚刚下载并安装了它(在此之前,您进行了apt-get update && apt-get upgrade,对吗?) - Ricket
4您可能还想卸载在UEFI系统中安装的linux-signed-image软件包:sudo apt-get purge linux-signed-image-3.11.0-{12,14,24}-generic,这将删除12、14和24版本。 - devius
对于那些上述步骤无效的人:运行df命令并查看/boot目录。如果它已经满了100%,你需要进入/boot目录,然后使用sudo rm命令删除一些旧的内核镜像。之后用df命令验证/boot目录是否有一些可用空间,并继续执行上述步骤(还要清理手动删除镜像的内核)。 - 0 _
purge实际上是做什么的?除了删除相关的config-initrdSystem.mapvmlinuz文件之外,还有其他操作吗?如果我只是想暂时将旧内核移开,我可以只移动这4个文件吗? - Bobby Jack
@BobbyJack,至少它会更新软件包管理数据库,并更新grub(以防内核包)。 - jarno
@devius 你知道在同一个系统中是否可能存在常规和签名图像吗? - jarno
@jarno 是的。我不知道这是否总是如此,但至少在我的系统上两种类型的图像都存在。我猜signed图像不会安装在非EFI系统中。 - devius
@devius 你能告诉我在命令ls -1v /boot/vmlinuz-*的输出中,与已签名内核相关的那一行是什么样子吗?是否有"signed"标签出现在其中?当你使用已签名内核时,uname -r命令的输出又是什么样子呢? - jarno
1@jarno 我不知道我是否正在使用已签名的内核,但是我的系统上的 uname -r 没有任何 signed 字符串。我似乎安装了一个已签名的映像,并且那个 ls 命令的输出是:/boot/vmlinuz-3.19.0-16-generic.efi.signed - devius
@devius,你不需要单独卸载linux-signed-image软件包。它们将作为常规通用linux-image软件包的依赖项自动清除。 - jarno
1如果你不小心删除了在_uname -r_中显示的内核,别担心;只需使用_sudo apt-get install linux-image-[在uname -r中显示的版本]-generic_重新安装即可。当然,这是假设你没有重启 ;) - Ricardo Velhote
如果旧内核位于其他(非启动)驱动器上,该怎么办? - Adam
当读取-r i时; do sudo apt-get purge $i ; done < <(sudo dpkg --list 'linux-image*' | grep linux-image | grep -v none| grep -v $(uname -r|cut -d'-' -f1) | awk '{print $2}') - Yordan Georgiev

我的一句话来删除旧内核(同时也释放磁盘空间)
dpkg --list | grep linux-image | awk '{ print $2 }' | sort -V | sed -n '/'`uname -r`'/q;p' | xargs sudo apt-get -y purge

解释(记住,| 使用前一个命令的输出作为下一个命令的输入)
- dpkg --list 列出所有已安装的软件包 - grep linux-image 查找已安装的 Linux 镜像 - awk '{ print $2 }' 只输出第二列(即软件包名称) - sort -V 按版本号对项目进行排序 - sed -n '/'`uname -r`'/q;p' 打印当前内核之前的行 - xargs sudo apt-get -y purge 清除找到的内核
解开 sed 的调用:
  • -n 告诉 sed 保持安静
  • `uname -r` 输出当前已安装的内核版本 - 我们使用反引号将其包含在命令中,以便输出作为命令的一部分(您也可能看到这样的写法:$(uname -r)
  • /something/q 表示当匹配到 'something' 时停止(在本例中,something 是 uname -r 的输出)- 斜杠用于包围正则表达式
  • p 是打印命令
  • ; 是命令分隔符,因此 /something/q;p 表示当匹配到 something 时退出,否则打印

综上所述,sed -n '/'`uname -r`'/q;p' 是打印直到与当前内核名称匹配的行。

如果你像我一样多疑,你可以将最后一部分改为 xargs echo sudo apt-get -y purge,这样旧内核清理命令会被打印出来,然后你可以在运行之前检查是否有意外的内容。


修改后的版本,去掉了标题:

dpkg --list | grep 'linux-image' | awk '{ print $2 }' | sort -V | sed -n '/'"$(uname -r | sed "s/\([0-9.-]*\)-\([^0-9]\+\)/\1/")"'/q;p' | xargs sudo apt-get -y purge
dpkg --list | grep 'linux-headers' | awk '{ print $2 }' | sort -V | sed -n '/'"$(uname -r | sed "s/\([0-9.-]*\)-\([^0-9]\+\)/\1/")"'/q;p' | xargs sudo apt-get -y purge

注意:sed调用已修改。`"$(uname -r | sed "s/\([0-9.-]*\)-\([^0-9]\+\)/\1/")"`仅提取版本号(例如"3.2.0-44"),而不包括"-generic"或类似的内容从`uname -r`中提取。
去除图片和页眉的全能版(整合了上面两个版本):
echo $(dpkg --list | grep linux-image | awk '{ print $2 }' | sort -V | sed -n '/'`uname -r`'/q;p') $(dpkg --list | grep linux-headers | awk '{ print $2 }' | sort -V | sed -n '/'"$(uname -r | sed "s/\([0-9.-]*\)-\([^0-9]\+\)/\1/")"'/q;p') | xargs sudo apt-get -y purge

2请注意,使用正则表达式来匹配当前内核版本可能有一定的风险:点号可以匹配任意字符,而3.1.2-23可以匹配到3.1.2-2(或者是反过来)。同样,请参考我的答案。 - jarno
21这里有一个调整过的一体化版本:sudo apt-get purge $(for tag in "linux-image" "linux-headers"; do dpkg-query -W -f'${Package}\n' "$tag-[0-9]*.[0-9]*.[0-9]*" | sort -V | awk 'index($0,c){exit} //' c=$(uname -r | cut -d- -f1,2); done) 也可以参考我的回答 - jarno
1@jarno 那真的对我帮助很大... 对你的简短回答表示赞赏 - Clain Dsilva
我将这与Kees Cook的head -n -2结合起来,以保留前两个图像。 - spume
5由于未满足的依赖关系,我需要使用dkpg -P来代替。这是完整的版本:dpkg --list | grep 'linux-headers' | awk '{ print $2 }' | sort -V | sed -n '/'"$(uname -r | sed "s/\([0-9.-]*\)-\([^0-9]\+\)/\1/")"'/q;p' | xargs sudo dpkg -P - Sebastian Sastre
你的最后一句话救了我免于节点耗尽的危机!给你点赞 :) - Peter Novotnak
或者只需删除 -y,这样在清除步骤上会出现确认对话框。 - Jeff Hammond
清理Yoda风格。应该是被接受的答案和得分最高的答案。 - kiltek
8不要这样做!“那个一行代码看起来有点危险,但是220个点赞的人肯定不会错!”我心想着并盲目地复制粘贴。重新启动后,直接进入GRUB界面。那个命令抹掉了我所有的内核,包括我正在使用的那一个。也许我当时在运行实时内核,甚至都记不清了。现在我正在家里四处找USB闪存驱动器,准备安装Ubuntu Live CD :( - Andreas Jansson
1今天在我旧的Ubuntu 12.04和14.04上运行得很好。 - tomfanning
在Mint 18.3上运行得非常顺利。 - JamalMcCrackin
安全地查看该命令将删除的内容。您可以先运行它,从最后一个 | 删除最后一部分。 然后它将只显示待删除的候选列表。 - jmary

Ubuntu 16.04+:

$ sudo apt autoremove
...
The following packages will be REMOVED:
  linux-headers-4.4.0-57 linux-headers-4.4.0-57-generic linux-image-4.4.0-57-generic linux-image-extra-4.4.0-57-generic linux-tools-4.4.0-57 linux-tools-4.4.0-57-generic

Ubuntu 15.10及以下版本:

我发现这是最简单和最快的方法。它保留了最新的内核以及另外两个:

sudo apt-get install bikeshed
sudo purge-old-kernels

更改保留的额外内核数量:
sudo purge-old-kernels --keep 3

1那个命令是一个shell脚本,你可以通过which purge-old-kernels找到它的位置。 - jarno
很高兴16.04版本让这个变得更容易了!希望这个答案能够继续得到认可... - Tobias J
在Ubuntu 16.04上,我有purge-old-kernels这个工具,它没有bikeshed(一些有用但尚未有固定位置的工具)包或任何特定的包。避免使用apt-get -y选项,就像闭上眼睛希望一切都会好起来一样。此外,在这里是_autoremove_决定保留多少旧内核的方式。 - Pablo Bianchi
2在16.04版本中,通过byobu软件包提供了purge-old-kernels功能(提示:apt-file search purge-old-kernels)。同意使用apt-get -y,我会将其移除。 - bmaupin
在Ubuntu 15.10及更早版本中,您也可以使用sudo apt-get autoremove。与您提到的sudo apt autoremove具有相同的功能。 - Dan
1@Dan,因为我不使用非LTS版本,所以我不确定具体是从什么时候开始的。但是我可以肯定地说,在14.04版本中,sudo apt-get autoremove命令不会删除内核。如果你知道具体的版本,请随时更新答案! - bmaupin
我在Ubuntu 14.04上尝试了purge-old-kernels命令,结果陷入了一个无限循环,一直提示错误!找不到您的内核头文件,内核版本为3.19.0-68-generic。经过50多次循环后,我终止了该命令,并手动运行了sudo update-grub命令... 祈祷我的系统还能正常启动。 - Communicative Algebra
原来我还有一个可引导的系统,而且purge-old-kernels确实释放了大约15 GB的磁盘空间。以下是我在杀死purge-old-kernels后用来恢复的完整命令序列:sudo rm /var/lib/dpkg/locksudo dpkg --configure -asudo update-grub - Communicative Algebra

从Grub 2中删除条目 应通过编辑或删除/etc/grub.d文件夹中的文件来删除条目。/boot/grub/grub.cfg文件是只读的,通常不需要进行编辑。
太多内核了吗?
- 如果您不确定当前使用的内核,请在终端中输入uname -r。 - 通过APT(Synaptic、"apt-get remove"等)删除的内核将自动更新grub.cfg,无需用户操作。 - 一个很好的用于删除内核(和菜单条目)的工具是Ubuntu-Tweak,这是一个安全且易于使用的GUI应用程序。 - 安装Ubuntu Tweak。 - Ubuntu-Tweak将在应用程序 > 系统工具下可用。
删除旧的内核条目。
  • 在左侧选择"Package Cleaner",从右面板选择"Clean Kernel"。

  • 点击右下角的"解锁"按钮,输入密码。

  • 从显示的列表中选择您希望删除的内核映像和头文件。正在使用的内核不会列出。

  • 点击右下角的"清理"按钮以删除所选的内核映像和头文件。

从Grub菜单中删除操作系统

  • 计算机中已删除的其他操作系统也将在以root身份运行"update-grub"命令后从菜单中删除。

  • 菜单项是由脚本放置在Grub2菜单上的。如果您不希望其他操作系统出现在菜单中,请禁用/etc/grub.d/30_osprober文件。

  • 运行以下命令停止该脚本的运行
    sudo chmod -x /etc/grub.d/30_os-prober

  • 在/etc/default/grub中设置DISABLE_30_OS-PROBER='true'

从Grub菜单中删除Memtest86+
sudo chmod -x /etc/grub.d/20_memtest86+

  • 运行update-grub命令以将更改合并到grub.cfg中

来源

注意: 在内核更新之后,GRUB菜单会添加一个新的条目。如果您希望,可以删除旧条目。然而,大多数经验丰富的用户会建议您至少保留一个备用条目,以防升级出现问题,并且您需要引导旧的内核版本进行故障排除。

删除内核条目的另一种方法(10.04之前)

适用于GRUB而非GRUB2

启动管理器 安装启动管理器

你可以在系统>>管理>>下找到它。 alt text
alt text
你看第二张截图,你可以选择显示多少个内核?通常我只保留一个,但是当我升级内核时,我总是在重新启动之前将其更改为2,这样如果新的内核与我的硬件有问题,我就可以选择旧的内核。一旦我知道新的内核运行良好,我就会将其改回1。


2实际上,在Ubuntu 10.04上,启动管理器并没有给我一个像这样的窗口,而是只给了一个有两个选项卡的窗口 -> 引导选项和高级选项.. 在高级选项中,并没有限制内核数量的选项。所以请更新针对Ubuntu 10.04的答案。(这也是我为什么给它投了反对票的原因..) - Navaneeth Sen
在没有安装图形用户界面(服务器)的机器上,如何定义“要保留的内核数量”这个概念呢?有什么想法吗? - sylvainulg
startupmanager已经过时了。 请查看grup-customizer - muhasturk

纯粹的命令行操作,这将删除除当前和倒数第二个(通过下面head命令中的“-2”)之外的所有内容。
OLD=$(ls -tr /boot/vmlinuz-* | head -n -2 | cut -d- -f2- |
    awk '{print "linux-image-" $0 " linux-headers-" $0}' )
if [ -n "$OLD" ]; then
    apt-get -qy remove --purge $OLD
fi
apt-get -qy autoremove --purge

9这里的一行命令:dpkg -l linux-* | awk '/^ii/{ print $2}' | grep -v -e `uname -r | cut -f1,2 -d"-"` | grep -e [0-9] | xargs sudo apt-get -y purge - Dmitry Verkhoturov
@DmitryPaskal,你应该将这个作为一个新的回答添加。 - saji89
10@dmitrypaskal 一如既往,不要只是复制黏贴而不理解它们。在我的机器上,这个一行代码也匹配 linux-libc-dev:amd64,这个不应该被删除。 - jamesadney
1@Kees Cook,awk参数应该只用单引号括起来吗?如果你的意图是在管道行前面添加"linux-image-",那么只有使用awk '{print "linux-image-" $0}'才能实现。 - Mark
这对我来说不起作用,它包含了我自定义安装的内核(Ubuntu 14.04 with 3.17)。 - Alex R
@axlroden 它如何知道安装了哪个自定义内核? - jarno
@axlroden 尝试使用命令 ls 的选项 -v 而不是 -t。 - jarno
@Mark 现在这个解决方案与清除旧内核的 purge-old-kernels(在 Universe 软件源中可用;Kees Cook 被标记为其中一位作者)类似,不同之处在于如果存在两个更新的内核,它可能会连同当前内核(通过 uname -r 显示)一起删除! - jarno
最后一行(带有autoremove)是否处理了linux-image-extras文件?有人可以修改它,以便我们还可以手动选择一些不在列表顶部的内核吗? - nyxee
@nyxee https://www.bountysource.com/issues/38892663-feature-request-basic-interactive-purging - jarno
@nyxee 或者甚至https://www.bountysource.com/issues/38300038-feature-request-the-command-should-work-like-this - jarno

更新:`purge-old-kernels` 现在已被弃用
我编写了一个脚本,可以在复杂条件下清除内核。它被称为 `linux-purge` ,你可以在这里找到它:这里
如果你只想在系统没有问题的情况下清除旧内核(以及相关软件包),可以使用 这个脚本
我还贡献了一个有关删除旧内核的 Ubuntu 文档页面,你可以在这里找到它:这里

看起来purge-old-kernels在bikeshed的precise版本(1.22)中不存在。有没有一种合理/安全的方法可以获取更近期的precise版本的bikeshed?或者只需安装脚本会更简单/更安全?尽管依赖项列表很长,但我更愿意使用一个仓库。 - drevicko
1@drevicko 点击这里查看。 - jarno
还有一个稍微离题的问题:除了去源代码查找,有没有办法确定在安装bikeshed时会有哪些命令可用? - drevicko
1@drevicko,好的,“dlocate -lsbin bikeshed” - jarno
1@drevicko, 还可以参考另一个问题 - jarno
@jarno 这两个版本的脚本功能有区别吗? sudo apt-get purge $(for tag in "linux-image" "linux-headers"; do dpkg-query -W -f'${Package}\n' "$tag-[0-9]*.[0-9]*.[0-9]*" | sort -V | awk 'index($0,c){exit} //' c=$(uname -r | cut -d- -f1,2); done) (2015)sudo apt-get purge $(dpkg-query -W -f'${Package}\n' 'linux-*' | sed -nr 's/.*-([0-9]+(\.[0-9]+){2}-[^-]+).*/\1 &/p' | sort -k 1,1V | awk '($1==c){exit} {print $2}' c=$(uname -r | cut -f1,2 -d-)) (更新的?) - ChrisW
1@ChrisW 是的,有最新版本。我刚刚对脚本进行了微小改进,所以最好使用最新版本。 - jarno

你可以按照Ubuntu Wiki上的自动安全更新文章中的"使用"unattended-upgrades"软件包部分"来执行此操作。
您需要更改/etc/apt/apt.conf.d/50unattended-upgrades文件中的以下行;
//Unattended-Upgrade::Remove-Unused-Dependencies "false";

使用

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

自动删除旧的软件包,包括内核。
还要删除或注释掉这一行。
"^linux-image.*"; 

在文件/etc/apt/apt.conf.d/01autoremove的"NeverAutoRemove"部分中。

2我做了这个,但它仍然在收集3个以上的旧内核,占用了数百兆字节的空间。所以我将apt-get autoremove添加到我的每日定时任务中,实际上是在进行升级时使用的,因为它并不总是通过内置的更新管理器完成。 - Marcos
我认为这只适用于Trusty版本,并且只适用于自动安装的内核。 - jarno
这对于防止自动升级软件包时旧内核的积累非常有用,例如使用无人值守升级。然而,如果您不重新启动,您可能会发现当前正在运行的内核的软件包已被卸载!这可能导致一个问题:您插入的新设备可能无法正常工作,因为它们的模块无法热加载,因为它们不再存在于您的硬盘上。(对此的快速修复方法只是再次安装内核包,然后拔出并重新插入设备。) - joeytwiddle
我为上述问题创建了一个自动化解决方案。如果你认为这是一个好方法,那么请随意将其添加到Qwerty的答案中。 - joeytwiddle

要确定已安装了哪些内核和头文件,请使用以下命令
dpkg -l | grep linux-image

dpkg -l | grep linux-headers

你可以逐个或一起删除它们,只需确保保留最近的一个。
还有一些方便的命令和脚本可以自动执行删除操作。

http://ubuntuforums.org/showthread.php?t=1658648

以下内容声称可以删除所有未使用的内核和头文件:
dpkg -l 'linux-*' | sed '/^ii/!d;/'"$(uname -r | sed "s/\(.*\)-\([^0-9]\+\)/\1/")"'/d;s/^[^ ]* [^ ]* \([^ ]*\).*/\1/;/[0-9]/!d'|grep -E "(image|headers|modules)" | grep -v hwe | xargs sudo apt-get purge

apt-get -y删除时不需要确认。
在18.04.1版本上运行的结果如下:
~$ dpkg -l 'linux-*' | sed '/^ii/!d;/'"$(uname -r | sed "s/\(.*\)-\([^0-9]

\+\)/\1/")"'/d;s/^[^ ]* [^ ]* \([^ ]*\).*/\1/;/[0-9]/!d'|grep -E "(image|headers|modules)" | xargs sudo apt-get -y purge
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following packages will be REMOVED:
  linux-headers-4.15.0-33* linux-headers-4.15.0-33-generic* linux-headers-4.15.0-34* linux-headers-4.15.0-34-generic* linux-image-4.15.0-33-generic* linux-image-4.15.0-34-generic*
  linux-modules-4.15.0-33-generic* linux-modules-4.15.0-34-generic* linux-modules-extra-4.15.0-33-generic* linux-modules-extra-4.15.0-34-generic*
0 upgraded, 0 newly installed, 10 to remove and 1 not upgraded.
After this operation, 671 MB disk space will be freed.
(Reading database ... 227403 files and directories currently installed.)
Removing linux-headers-4.15.0-33-generic (4.15.0-33.36) ...
Removing linux-headers-4.15.0-33 (4.15.0-33.36) ...
Removing linux-headers-4.15.0-34-generic (4.15.0-34.37) ...
Removing linux-headers-4.15.0-34 (4.15.0-34.37) ...
Removing linux-modules-extra-4.15.0-33-generic (4.15.0-33.36) ...
Removing linux-image-4.15.0-33-generic (4.15.0-33.36) ...
/etc/kernel/postrm.d/initramfs-tools:
update-initramfs: Deleting /boot/initrd.img-4.15.0-33-generic
/etc/kernel/postrm.d/zz-update-grub:
Generating grub configuration file ...
Found linux image: /boot/vmlinuz-4.15.0-36-generic
Found initrd image: /boot/initrd.img-4.15.0-36-generic
Found linux image: /boot/vmlinuz-4.15.0-34-generic
Found initrd image: /boot/initrd.img-4.15.0-34-generic
Adding boot menu entry for EFI firmware configuration
done
Removing linux-modules-extra-4.15.0-34-generic (4.15.0-34.37) ...
Removing linux-image-4.15.0-34-generic (4.15.0-34.37) ...
I: /vmlinuz.old is now a symlink to boot/vmlinuz-4.15.0-36-generic
I: /initrd.img.old is now a symlink to boot/initrd.img-4.15.0-36-generic
/etc/kernel/postrm.d/initramfs-tools:
update-initramfs: Deleting /boot/initrd.img-4.15.0-34-generic
/etc/kernel/postrm.d/zz-update-grub:
Generating grub configuration file ...
Found linux image: /boot/vmlinuz-4.15.0-36-generic
Found initrd image: /boot/initrd.img-4.15.0-36-generic
Adding boot menu entry for EFI firmware configuration
done
Removing linux-modules-4.15.0-33-generic (4.15.0-33.36) ...
Removing linux-modules-4.15.0-34-generic (4.15.0-34.37) ...
(Reading database ... 156180 files and directories currently installed.)
Purging configuration files for linux-image-4.15.0-34-generic (4.15.0-34.37) ...
Purging configuration files for linux-modules-4.15.0-33-generic (4.15.0-33.36) ...
dpkg: warning: while removing linux-modules-4.15.0-33-generic, directory '/lib/modules/4.15.0-33-generic' not empty so not removed
Purging configuration files for linux-modules-4.15.0-34-generic (4.15.0-34.37) ...
Purging configuration files for linux-image-4.15.0-33-generic (4.15.0-33.36) ...
Purging configuration files for linux-modules-extra-4.15.0-34-generic (4.15.0-34.37) ...
Purging configuration files for linux-modules-extra-4.15.0-33-generic (4.15.0-33.36) ...
~$ uname -r
4.15.0-36-generic

你在论坛上找到的脚本有问题。它可能无法删除一些所需的头文件包(如果你使用一些旧的-pae内核),另一方面,它可能会删除一些你想要保留的包。 - jarno
感谢您的评论。这个脚本可能不完美,但是我已经用了多年了,主要在12.04和14.04上使用过,32位和64位系统,没有遇到任何问题。另外,linux-libc-dev 已经安装了。 - mikewhatever
我猜linux-libc-dev的版本号与当前内核的版本号相匹配。在这里,dpkg -l linux-libc-dev | sed '/^ii/!d;s/^[^ ]* [^ ]* \([^ ]*\).*/\1/;/[0-9]/!d'打印出了linux-libc-dev:amd64。 - jarno
尽管如此,我仍然无法复现你的发现。为了安全起见,我已经修改了命令,添加了一个额外的过滤器 - grep -E "(image|headers)" - mikewhatever
然后脚本可能会留下额外安装的软件包。我认为你可以通过运行 apt-cache search --names-only "^linux-.*" | cut -d' ' -f1 | grep -E -e linux-.*-[0-9]+(\.[0-9]+){2}-[^-]+ 来查看不同类型的可能软件包。 - jarno
1以下是执行原始脚本的方法: sudo apt-get purge $(dpkg -l 'linux-*' | tail -n +6 | awk -v c="$(uname -r | cut -d- -f1,2)" 'match($2,"[0-9]+\\.[0-9]+\\.[0-9]+-[^-]+") && substr($2,RSTART,RLENGTH)!=c {print $2}') 或者使用更简单的 dpkg-query: sudo apt-get purge $(dpkg-query -W 'linux-*' | awk -v c="$(uname -r | cut -d- -f1,2)" 'match($1,"[0-9]+\\.[0-9]+\\.[0-9]+-[^-]+") && substr($1,RSTART,RLENGTH)!=c {print $1}') - jarno
1请先尝试不使用-y标志进行清理。 - Melroy van den Berg

已经随 Ubuntu 自带的最快/简单的方法(至少适用于 12.04)是使用 apt-get 命令。如果您希望删除所有未使用的旧内核版本(除了您当前正在使用的上一个版本),请按照以下步骤操作。这样做是为了确保如果当前的内核版本出现故障,您有一种返回到之前状态的方法。请按照以下步骤操作:

sudo apt-get autoclean

这将清除您可能拥有的任何旧文件(包括内核版本)。请注意,如果您有很多旧版本,由于需要确保删除内核版本没有问题,这将需要一些时间。对我来说,删除最近的12个内核版本大约需要2分钟。您还可以执行以下操作:
sudo apt-get clean

这将清除apt缓存文件夹中下载和存储的所有内容。最后你会得到:
sudo apt-get autoremove

检查并删除任何未使用的软件包(如果需要)是非常有用的,特别是对于不再被任何已安装应用程序所需的库和依赖软件包。

1我想这在更新的版本中已经改变了,因为在14.04中,它只是清理软件包缓存,不会影响已安装的软件包或grub。 - jarno
2我可以确认sudo apt-get autoremove确实会删除14.04中旧的(超过一个版本之前的)内核。在升级内核之前和之后,您可能需要运行它。当我在升级之前运行时,它只删除了旧内核的通用版本。然后,在升级内核后,它也删除了旧内核的低延迟版本。 - tekNorah
我是指 sudo apt-get autoclean 命令。@tekNorah 我安装了几个旧内核,然后在Ubuntu Studio 14.04中运行了 sudo apt-get autoremove 命令。它没有删除任何内核。我只安装了低延迟内核。你为什么同时安装了 -generic 和 -lowlatency 内核? - jarno
5是的,这对我非常有效,彻底清理了所有旧内核,并且不依赖于疯狂的一行脚本!强烈推荐,真希望我可以多次点赞! - Jeff Atwood
如果我没记错的话,早期版本的Ubuntu衍生版在默认情况下不会通过apt-get autoremove删除内核。我认为如果他们这样做了,这个帖子可能会有很大的不同。你对这个什么时候改变的有更准确的信息吗?顺便说一句,apt-mark showmanual | grep -E linux-.+-[0-9.]+-.+仍然显示内核包是手动安装的。 - jarno
@jarno 你是正确的,它没有自动完成。现在我只有一个内核,但当它们开始累积时,我会更新帖子。如果你找到了最近的例子可以使用,请随时更新这个。 - Luis Alvarado
@tekNorah,另外sudo apt-get --purge autoremove在Mythbuntu 14.04中并不能删除旧内核,但在Xubuntu 15.10中似乎可以做到。 - jarno
@tekNorah,嗯,它确实会在设置了14.04的安全更新自动安装后删除已安装的旧内核(自动)。请参阅错误报告 - jarno
1@JeffAtwood 嗯,这可能会删除更多的内核,不过是安全的。请参见错误报告 - jarno