1. 项目概述为什么GRUB启动项会“冗余”如果你在电脑上安装了Ubuntu尤其是和Windows组成了双系统那么开机时看到的那个黑底白字的菜单就是GRUB。GRUB全称是GRand Unified Bootloader是Linux世界里最常用的启动引导程序它的任务很简单在电脑通电自检后接管控制权然后列出所有可启动的操作系统让你选择。听起来很美好对吧但问题往往就出在这个“列出所有”上。我遇到过太多朋友来问“我电脑上明明只有一个Ubuntu和一个Windows为什么GRUB菜单里会多出来好几个‘Ubuntu’选项甚至还有一堆带‘Advanced options’的旧内核条目” 或者更棘手的是“我已经把Windows系统盘整个格式化了为什么开机还是卡在GRUB进不去剩下的Ubuntu” 这些就是我们今天要处理的“冗余”或“失效”的GRUB启动项。它们不仅让开机选择界面变得杂乱更可能在系统变更后导致无法正常启动让人头大。简单来说删除这些多余的GRUB启动项核心目标有两个一是净化启动菜单让界面清爽只保留真正有用的选项二是修复启动链确保在删除某个系统或分区后剩下的系统能顺利引导避免开机直接掉进grub命令行这种“恐怖片”场景。这个过程并不复杂但需要对GRUB的工作原理和Linux的文件系统结构有最基本的了解。别担心我会带你一步步拆解从“为什么”到“怎么做”再到“万一搞砸了怎么办”把这条路上的坑都给你标出来。2. GRUB启动项管理核心原理拆解在动手删除任何东西之前我们必须先搞清楚GRUB是怎么工作的以及它从哪里读取这些启动项信息。知其然更要知其所以然这样才能在出问题时心里不慌。2.1 GRUB 2的工作流程与配置文件架构现代的Ubuntu使用的都是GRUB 2与古老的GRUB Legacy不同。它的引导过程可以简化为BIOS/UEFI - GRUB核心映像core.img -/boot/grub/grub.cfg- 加载操作系统。这里的关键是/boot/grub/grub.cfg文件。这个文件定义了你在启动菜单中看到的所有条目。但是你绝对不应该直接手动编辑这个文件因为它是自动生成的。在它的开头通常会有这么一行注释# DO NOT EDIT THIS FILE那么这个文件是根据什么生成的呢答案藏在/etc/default/grub和/etc/grub.d/目录里。/etc/default/grub这是主配置文件定义了一些全局变量比如默认启动项、超时时间、是否显示隐藏菜单等。我们常用的GRUB_TIMEOUT菜单显示时间、GRUB_DEFAULT默认选中项就在这里设置。/etc/grub.d/这个目录下存放着一系列脚本通常以数字开头如10_linux,30_os-prober等。这些脚本才是真正的“菜单生成器”。当执行sudo update-grub命令时系统会按照数字顺序依次运行这些脚本它们会探测系统中的可启动内核和操作系统并将结果汇总最终生成/boot/grub/grub.cfg。2.2 启动项来源分析内核、系统探测与自定义理解了生成机制我们就能明白冗余启动项从哪里来旧内核条目最常见由/etc/grub.d/10_linux脚本生成。Ubuntu在更新内核时默认会保留旧内核以防新内核有问题可以回退。这会导致/boot分区里存有多个内核文件vmlinuz-xxx和initrd.img-xxx每个内核都会在GRUB菜单中生成一个主条目和一个“Advanced options”下的恢复模式条目。这是菜单冗长的首要原因。其他操作系统条目由/etc/grub.d/30_os-prober脚本生成。这个脚本会扫描你电脑上的所有磁盘分区寻找Windows、其他Linux发行版等并为它们创建启动项。当你卸载了某个系统但没清理分区或者该脚本探测有误时就会产生无效条目。内存测试工具等由/etc/grub.d/20_memtest86等脚本生成。自定义静态条目由/etc/grub.d/40_custom脚本生成。用户可以在这里手动添加一些特殊的启动命令比如用来引导ISO镜像。如果这里写了多余的内容也会出现在菜单里。所以删除启动项的本质就是通过合理配置或禁用上述脚本来影响update-grub命令的生成结果而不是去动最终的那个grub.cfg。2.3 关键命令update-grub与grub-install的角色在整个过程中两个命令至关重要sudo update-grub这是我们最常用的命令。它的作用就是调用上述脚本重新生成/boot/grub/grub.cfg文件。任何对配置/etc/default/grub或/etc/grub.d/下的脚本的修改都必须通过运行这个命令来生效。sudo grub-install /dev/sdX这个命令的作用是将GRUB的引导程序第一阶段和1.5阶段安装或修复到指定磁盘如/dev/sda的MBR主引导记录或UEFI系统的ESPEFI系统分区中。它处理的是“如何找到GRUB”的问题。当你删除了一个系统尤其是Windows导致GRUB环境变量指向了不存在的分区从而无法启动时就需要在Live CD环境下使用这个命令来修复引导。重要心得一定要分清update-grub和grub-install。前者是“更新菜单内容”后者是“修复引导程序本身”。90%的菜单清理工作只需要和update-grub打交道。3. 实战操作精准定位与删除冗余启动项理论清楚了我们进入实战环节。请记住所有操作都需要在终端中拥有管理员权限使用sudo。操作前强烈建议先备份关键的配置文件sudo cp /etc/default/grub /etc/default/grub.backup sudo cp -r /etc/grub.d /etc/grub.d.backup这样万一操作失误我们还有回滚的余地。3.1 场景一清理旧内核条目最安全、最常用这是净化菜单最立竿见影的方法。Ubuntu默认会保留多个旧内核通常我们只需要保留最新的1-2个即可。方法A使用图形化工具ubuntu-tweak已不维护或命令行工具更推荐使用命令行直接、可控。查看当前已安装的所有内核dpkg --list | grep linux-image你会看到类似下面的列表ii表示已安装。ii linux-image-5.15.0-60-generic 5.15.0-60.66... amd64 Signed kernel image generic ii linux-image-5.15.0-67-generic 5.15.0-67.74... amd64 Signed kernel image generic ii linux-image-5.15.0-69-generic 5.15.0-69.76... amd64 Signed kernel image generic ii linux-image-generic-hwe-22.04 5.15.0.69.76... amd64 Generic Linux kernel image确定要删除的旧内核通常除了最新的一个或两个上例中-69和-67其他的都可以考虑删除。同时注意每个linux-image包通常对应一个linux-headers包和linux-modules包最好一并清理。使用apt或apt-get命令删除sudo apt remove linux-image-5.15.0-60-generic linux-headers-5.15.0-60 linux-modules-extra-5.15.0-60-generic或者使用autoremove自动清理不再需要的依赖包括旧内核sudo apt autoremoveautoremove会智能地移除那些被自动安装、但现在没有任何其他软件包依赖的包旧内核包常常属于此类。更新GRUB配置sudo update-grub完成后重启你会发现“Advanced options”子菜单里的旧内核条目消失了菜单清爽了很多。实操心得不要一看到旧内核就删。确保你当前正在运行的内核工作正常。你可以用uname -r查看当前内核版本。保留一个可用的旧内核作为“安全垫”在新内核出问题时可以回退这是一个好习惯。通常保留最新的2-3个内核是比较平衡的选择。3.2 场景二禁用或移除其他操作系统探测如果你已经彻底移除了Windows或其他Linux系统但GRUB菜单里还有它的选项这是因为30_os-prober脚本还在“多管闲事”。方法A临时禁用os-prober推荐最安全的方法是让这个脚本不运行而不是删除它。通过修改脚本的可执行权限来实现sudo chmod -x /etc/grub.d/30_os-prober-x参数是移除可执行权限。这样update-grub时就会跳过这个脚本。如果想恢复使用sudo chmod x /etc/grub.d/30_os-prober。方法B直接删除或备份移走更彻底sudo mv /etc/grub.d/30_os-prober /etc/grub.d/30_os-prober.disabled移动文件比改权限更直观想恢复时再移回来即可。方法C修改全局配置禁止探测特定分区更精细如果你只是不想探测某个特定分区比如一个存数据的NTFS分区被误认为是Windows可以在/etc/default/grub文件中添加GRUB_DISABLE_OS_PROBERtrue然后执行sudo update-grub。这将完全禁用os-prober。完成上述任一操作后别忘了sudo update-grub3.3 场景三处理自定义启动项与内存测试项移除内存测试项如果你确定不需要内存测试工具可以像禁用30_os-prober一样移除20_memtest86脚本的执行权限或移动它。sudo chmod -x /etc/grub.d/20_memtest86 sudo update-grub清理自定义条目检查/etc/grub.d/40_custom文件删除里面你不再需要的自定义启动项配置。这个文件默认是空的如果你没手动加过东西就不用管。3.4 场景四手动编辑GRUB配置文件高级操作虽然不推荐直接改grub.cfg但有时我们需要手动调整菜单顺序、隐藏某个条目或者修改内核启动参数。这时可以通过修改/etc/default/grub和/etc/grub.d/下的脚本来实现。例如调整默认启动项 在/etc/default/grub中GRUB_DEFAULT可以设置为数字从0开始计数对应菜单项顺序也可以设置为保存的条目名称如“Ubuntu”。更可靠的是使用GRUB_SAVEDEFAULT和grub-reboot/grub-set-default命令来管理。隐藏某个特定的菜单项比如某个内核比较麻烦通常需要修改10_linux脚本的逻辑这对新手不友好。更简单的方法是直接删除对应的内核包如场景一所述。修改完配置后永恒不变的步骤sudo update-grub4. 深度排查与修复当删除导致启动失败时这是大家最害怕的情况一顿操作后重启电脑没有看到熟悉的GRUB菜单而是出现了一个孤零零的grub提示符或者直接黑屏报错。别慌这通常意味着GRUB的引导程序找不到它需要的配置文件或核心映像了。4.1 原因分析为什么删除系统后会“掉进GRUB救援模式”在Windows和Ubuntu双系统环境下GRUB通常被安装在Ubuntu所在磁盘的MBR或者UEFI模式下的ESP分区中。GRUB的配置文件grub.cfg和内核文件都存放在Ubuntu的/boot分区里。当你直接格式化或删除了Windows分区如果这个操作改变了磁盘的分区编号例如原来的sda3变成了sda2那么GRUB在早期引导阶段其内置的环境变量可能仍然指向旧的分区路径去查找/boot/grub。路径一旦对不上它就“迷路”了无法加载后续的配置和系统于是把你扔到救援模式。4.2 解决方案使用Live CD/USB修复GRUB引导你需要一个Ubuntu安装U盘就是当初装系统用的那个。用U盘启动电脑选择“试用Ubuntu”Try Ubuntu进入Live桌面环境。挂载原系统根分区 首先用sudo fdisk -l或图形化磁盘工具找到你原来的Ubuntu系统根分区/和/boot分区如果单独分区了。假设你的根分区是/dev/sda5。执行挂载sudo mount /dev/sda5 /mnt如果/boot是单独分区比如/dev/sda6也需要挂载sudo mount /dev/sda6 /mnt/boot对于UEFI系统还需要挂载ESP分区通常是FAT32格式如/dev/sda1sudo mount /dev/sda1 /mnt/boot/efi绑定虚拟文件系统让chroot环境正常工作sudo mount --bind /dev /mnt/dev sudo mount --bind /dev/pts /mnt/dev/pts sudo mount --bind /proc /mnt/proc sudo mount --bind /sys /mnt/sys sudo mount --bind /run /mnt/run # 如果存在/run目录切换根目录到原系统chrootsudo chroot /mnt现在你的终端就“进入”了原来的Ubuntu系统。重新安装/修复GRUB到磁盘对于传统的BIOS/MBR启动方式grub-install /dev/sda # 注意是磁盘sda不是分区sda5对于UEFI启动方式grub-install --targetx86_64-efi --efi-directory/boot/efi --bootloader-idUbuntu--bootloader-id会决定在UEFI启动菜单中显示的名称。重新生成GRUB配置文件update-grub这个命令会重新探测当前系统内的操作系统此时应该只有Ubuntu了生成正确的grub.cfg。退出并重启exit # 退出chroot环境 sudo umount -a /mnt # 卸载所有挂载点 sudo reboot拔掉U盘电脑应该就能正常启动到GRUB菜单并且只显示Ubuntu的选项了。避坑指南在Live环境下最容易出错的一步是挂载。务必确认你挂载的分区是正确的根分区和/boot分区。如果不确定可以在挂载后chroot之前用ls /mnt看看里面是不是有etc,home,usr等熟悉的目录。UEFI修复时--efi-directory参数必须指向已挂载的ESP分区路径。4.3 预防措施如何安全地卸载双系统中的另一个系统如果你想移除Windows最安全的方法不是直接在磁盘管理里删除分区而是按以下顺序操作在Windows内备份所有数据。进入Ubuntu系统使用gparted需安装或gnome-disks工具删除Windows对应的分区通常是NTFS格式。将腾出来的空间合并或扩展到你Ubuntu的分区上此操作有风险务必提前备份重要数据。关键一步在Ubuntu中执行sudo update-grub。让GRUB知道Windows已经不存在了。对于UEFI系统你还可以使用efibootmgr命令来删除UEFI固件中无效的Windows启动项sudo efibootmgr # 查看所有启动项记下Windows对应的BootXXXX编号 sudo efibootmgr -b XXXX -B # 删除编号为XXXX的启动项按照这个流程可以最大程度避免GRUB引导失败的问题。5. 高级技巧与自动化管理对于追求效率或者需要频繁维护多台机器的用户一些进阶技巧能让GRUB管理变得更轻松。5.1 使用grub-customizer图形化工具如果你对命令行发怵可以安装一个强大的图形化工具sudo add-apt-repository ppa:danielrichter2007/grub-customizer sudo apt update sudo apt install grub-customizer安装后在应用菜单里搜索打开。你可以可视化的调整菜单项的顺序。重命名、隐藏或删除启动项。修改超时时间和默认启动项。更改GRUB的界面主题。它的所有操作本质上都是在后台帮你修改/etc/default/grub和/etc/grub.d/下的文件然后自动调用update-grub。对于新手来说非常友好但资深用户往往更喜欢直接操控配置文件因为更透明、更可控。5.2 自动化清理旧内核脚本你可以创建一个简单的Shell脚本放在/etc/cron.weekly/目录下让它每周自动清理旧内核只保留最新的2个。下面是一个示例脚本autoremove-old-kernels#!/bin/bash # 保留最新内核的数量 KEEP2 # 获取当前正在运行的内核版本 CURRENT$(uname -r | sed s/-generic//) # 获取所有已安装的linux-image包按版本排序排除当前运行的和最新的KEEP个 OLD_KERNELS$(dpkg --list | grep ^ii | grep -E linux-image-[0-9] | awk {print $2} | sort -V | grep -v $CURRENT | head -n -$KEEP) if [ -n $OLD_KERNELS ]; then echo 准备自动移除以下旧内核包 echo $OLD_KERNELS # 这里可以选择直接执行删除或者先打印出来确认 # sudo apt purge -y $OLD_KERNELS # sudo update-grub else echo 没有需要清理的旧内核。 fi注意自动删除有风险。建议先让脚本以“仅报告”模式运行几周确认其行为符合预期后再取消注释删除和更新GRUB的命令行并谨慎设置KEEP的数量建议至少为2。5.3 备份与恢复GRUB配置一套好的GRUB配置是值得备份的。备份其实很简单# 备份配置 sudo tar -czvf ~/grub-backup-$(date %Y%m%d).tar.gz /etc/default/grub /etc/grub.d/ /boot/grub/grub.cfg # 恢复配置在需要时 # 首先将备份文件解压到临时目录 # 然后覆盖现有文件请确保在Live环境或确定当前GRUB能启动的情况下操作 sudo cp /tmp/grub-backup/etc/default/grub /etc/default/ sudo cp -r /tmp/grub-backup/etc/grub.d/* /etc/grub.d/ sudo cp /tmp/grub-backup/boot/grub/grub.cfg /boot/grub/ # 最后根据情况决定是否运行 update-grub 或 grub-install对于UEFI系统ESP分区中的GRUB模块通常位于/boot/efi/EFI/Ubuntu/也很重要可以考虑一并备份。我个人更倾向于将/etc/default/grub和/etc/grub.d/40_custom这类自己修改过的配置文件用版本控制系统如Git进行管理这样每次更改都有记录回滚也方便。6. 常见问题排查与解决方案实录即使按照步骤操作也可能会遇到一些意外情况。这里记录了几个我踩过的坑和解决方案。问题1执行sudo update-grub后毫无变化菜单依旧。可能原因1你没有正确禁用生成脚本。用ls -l /etc/grub.d/检查脚本的执行权限x确保30_os-prober等脚本已被去除x。可能原因2/boot/grub/grub.cfg文件被设置为只读检查其权限ls -l /boot/grub/grub.cfg。正常情况下update-grub会覆盖它。排查命令可以手动运行脚本看输出sudo /etc/grub.d/30_os-prober或者查看update-grub的详细日志sudo update-grub 21 | tee update-grub.log。问题2删除了旧内核但“Advanced options”里还有它的恢复模式条目。原因这通常是因为只删除了linux-image包但对应的linux-headers和linux-modules-extra包还在。update-grub的脚本可能根据这些残留包的信息生成了不完整的条目。解决用dpkg --list | grep linux彻底检查并清理所有相关包然后再次sudo update-grub。问题3UEFI模式下修复GRUB后启动时出现了两个“Ubuntu”选项。原因UEFI固件的启动管理列表NVRAM里存在重复或陈旧的Ubuntu启动项。当你用grub-install安装时它可能会添加一个新的而旧的没有被移除。解决进入UEFI固件设置开机按F2/Del等键在“启动选项”Boot Options里删除多余的Ubuntu条目。或者在Ubuntu系统内使用efibootmgr命令sudo efibootmgr # 查看所有记下重复项的编号 sudo efibootmgr -b XXXX -B # 删除编号为XXXX的项问题4在虚拟机如VMware中安装Ubuntu后GRUB菜单不显示直接进入系统。原因虚拟机BIOS的启动等待时间可能很短或者GRUB菜单被隐藏了。解决编辑/etc/default/grub确保GRUB_TIMEOUT的值大于0例如GRUB_TIMEOUT5并且注释掉或确保GRUB_HIDDEN_TIMEOUT相关行不起作用。然后sudo update-grub。在VMware启动时快速按ESC键也可以强制调出GRUB菜单。问题5想彻底重置GRUB配置到安装时的默认状态。方法重新安装GRUB包。这会覆盖/etc/grub.d/下的脚本和/etc/default/grub文件注意备份你的自定义设置。sudo apt install --reinstall grub-pc grub-common # BIOS系统 # 或 sudo apt install --reinstall grub-efi-amd64 grub-common # UEFI 64位系统 sudo update-grub管理GRUB启动项本质上是在管理系统的引导入口和启动环境。保持谨慎操作前备份、理解原理明白每个命令在做什么、善用工具就能让它服服帖帖。最关键的永远是那句老话不要在生产环境或没有备份的情况下进行不熟悉的系统级操作。对于个人电脑至少确保重要数据已备份并准备好一个系统安装U盘作为“救命稻草”这样无论遇到什么GRUB问题你都有底气从容解决。