开机之后没看到熟悉的桌面或者登录界面,屏幕上顶着一行grub>或者grub rescue>,下面还跟着一句minimal bash-like line editing is supported。第一次遇到的人十有八九会慌,以为系统挂了,其实大部分情况下数据都还在,只是引导这块断了线。这篇文章就是专门聊这个问题的,从命令行手动引导,到修复,再到怎么防止下次再犯,一步一步讲清楚。
我会把我在实际环境里排查过的案例、踩过的坑、用过的土办法都放进来。不管你是 Ubuntu、Debian、Arch 还是 CentOS 系的发行版,核心思路都是通用的,差别只在个别命令和配置文件路径上。
1. 先搞清楚问题本质:grub 命令行是怎么出现的
1.1 你遇见的到底是哪种界面
很多人把grub>和grub rescue>混为一谈,但这两者的问题阶段完全不同,处理方式也不一样。
grub rescue>是 GRUB 的救援模式。GRUB 自己在启动的时候,连核心模块(比如 normal.mod)都没找到,或者加载失败,就退到了这个最简环境。这个模式下能用的命令非常少,基本只有ls、set、unset、insmod这几个。想要脱离它,操作起来会比较繁琐,一般得先手动找到分区,再一步步insmod加载模块,最后normal进入完整命令行。
grub>是 GRUB 正常模块加载之后、但找不到或者无法读取 grub.cfg 时的状态。屏幕上方会有个大标题 "GNU GRUB version 2.xx",底部提示minimal bash-like line editing is supported。在这个界面,你能用的命令全多了,TAB 键能自动补全,也可以直接配置 root、加载内核、启动系统。对比起来,grub>的修复成本其实比grub rescue>低很多。
判断一下你眼前是哪个提示符,后面要做的操作完全不一样。这一步没辨清楚,很容易在错误的路径上白折腾。
1.2 最常见的几个诱因
从真实故障案例来看,grub 走到命令行模式,基本逃不开下面几类原因。
第一类是 grub.cfg 文件丢失、损坏或者被移动。这个文件通常位于/boot/grub/grub.cfg,它是整个引导菜单的配置文件。系统升级时中途断电、磁盘空间写满、误操作删除,都可能让它坏掉。
第二类是分区表或者分区 UUID 变化了。GRUB 在配置文件里大量使用 UUID 来定位分区,比如search --no-floppy --fs-uuid --set=root xxxxxxxx。如果你用 GParted 改过分区、格式化过某个分区、克隆过磁盘,UUID 就变了,GRUB 按旧 ID 找不到对应分区,自然就启动不了。
第三类是 Windows 更新把引导给覆盖了。双系统用户特别容易碰这个情况。Windows 在更新或者修复引导的过程中,会重新写入自己的 EFI 启动项,把 GRUB 从启动序列里挤出去,或者直接覆盖掉 EFI 分区里的引导文件。黑屏后你甚至可能直接进到 Windows 的恢复界面,而不是 grub 命令行,但两者本质都是引导冲突。
第四类是装了新内核之后,initramfs 或者 vmlinuz 文件缺失。比如/boot分区空间不够,内核升级时没写全,GRUB 能读取配置,但配置里指向的内核文件不存在,也会打进命令行或直接报error: file not found。
第五类是 BIOS 引导模式切换导致的。原来用传统 BIOS 模式装的系统,在 BIOS 里改成了 UEFI 模式,或者反过来。GRUB 安装位置彻底变了,MBR 里的引导代码和 EFI 分区里的引导文件完全不匹配,机器当然找不到正常引导项。
1.3 为什么 BIOS 和 UEFI 环境下的表现不一样
这俩环境底下,GRUB 的工作原理差得很远,理解这点才能知道该怎么修。
传统 BIOS 模式,机器一开机,CPU 会跳到一个固定地址,BIOS 去读启动盘的第一个扇区(MBR),MBR 里的 GRUB 引导代码接着去加载 core.img,然后按配置一步步把 Linux 内核拉起来。也就是说,引导代码是直接写在硬盘的开头位置的。
UEFI 模式下,主板会读取 EFI 系统分区(ESP,一般是 FAT32 格式)里的.efi文件。GRUB 的启动文件是EFI/grub/grubx64.efi,NVRAM 里记录着要加载哪个 .efi 文件。你可以理解成 UEFI 是一个小操作系统,它把启动项列表存进自己的配置区里,然后按顺序加载。这也就是为什么 UEFI 环境出问题,往往要去检查efibootmgr里的启动项顺序,而不只是重写 MBR。
我见过不少人在 UEFI 机器上用grub-install /dev/sda这种方式来修引导,结果重启还是进不了系统。原因很简单,UEFI 模式下要指定--target=x86_64-efi --efi-directory=...,不写的话,命令默认按 BIOS 方式安装,方向就错了。
2. 现场急救:grub 命令行下手动引导系统启动
2.1 先看清当前处境:ls 和 set
既然已经停在 grub 命令行,与其干瞪眼,不如先手动把系统拉起来。这套操作我做过无数次,思路非常简单:确认分区、指定 root、加载内核、启动。
进入 grub 命令行第一步就是ls。这个命令会列出当前 GRUB 能看到的所有磁盘和分区,输出大致长这样:
(hd0) (hd0,gpt1) (hd0,gpt2) (hd0,gpt3)(hd0)是第一块物理硬盘,(hd0,gpt1)表示硬盘上的第一个 GPT 分区。传统 MBR 分区表标识通常是(hd0,msdos1)这种写法。通过分区编号和文件系统内容,我们能判断出哪个分区是 EFI 分区、哪个是根分区、哪个是 /boot。
接着用set看一下当前的 GRUB 变量:
grub> set cmdpath=(hd0,gpt1)/EFI/grub prefix=(hd0,gpt1)/grub root=hd0,gpt1这里prefix告诉你去哪儿找 GRUB 的模块和配置文件,root是当前 GRUB 认为的根分区。如果这个 root 指向不对,后面加载东西都会报错。
这时候要做的,就是找到真正的 Linux 根分区。可以用ls (hd0,gpt2)/一类的命令去翻每个分区的内容。看到etc/、usr/、var/这些目录,说明这就是根分区;看到vmlinuz-*、initrd.img-*、grub/这些,说明是 /boot(可能独立,也可能就在根分区里)。
2.2 手动引导 Linux 内核启动的完整步骤
找到根分区之后,手动引导的过程就很机械了。假设系统根分区是(hd0,gpt3),/boot 没有单独分区,全部在根分区里,一套标准命令如下:
grub> set root=(hd0,gpt3) grub> linux /boot/vmlinuz-5.15.0-91-generic root=/dev/sda3 grub> initrd /boot/initrd.img-5.15.0-91-generic grub> boot第一行告诉 GRUB 根分区在哪,第二行指定要启动的内核文件,同时通过root=/dev/sda3告诉 Linux 内核,系统真正的根文件系统是哪个设备。第三行加载 initramfs,这个文件包含驱动的初始环境和根文件系统挂载工具,没有它内核没法挂载真正的 root。最后boot启动。
如果 /boot 是独立分区,命令会变成这样:
grub> set root=(hd0,gpt2) grub> linux /vmlinuz-5.15.0-91-generic root=/dev/sda3 grub> initrd /initrd.img-5.15.0-91-generic grub> boot差别就是内核和 initrd 的路径前面不用加/boot,因为整个分区挂载点就是 /boot。
实际操作时,TAB 键补全非常关键。忘掉了确切的内核版本号也没关系,输入linux /boot/vmlinuz-之后按 TAB,GRUB 会自动把存在的内核文件名补全出来。同理root=后也可以多试试,拿不准根分区设备号时,可以直接写root=UUID=xxxx,这个 UUID 可以通过ls -l /dev/disk/by-uuid/或者blkid查到,比设备名更保险。
2.3 特殊文件系统:LVM、btrfs、加密分区
如果根分区用了 LVM、btrfs 子卷或者 LUKS 加密,手动引导时就得先加载对应模块,否则 GRUB 认不出这些文件系统。
遇到 LVM 逻辑卷,先执行:
grub> insmod lvm grub> ls (lvm/ubuntu-vg-root)/这里(lvm/ubuntu-vg-root)的 pq 是「卷组名/逻辑卷名」。找对了之后设置 root 并加载内核:
grub> set root=(lvm/ubuntu-vg-root) grub> linux /boot/vmlinuz-... root=/dev/mapper/ubuntu-vg-root grub> initrd /boot/initrd.img-... grub> bootbtrfs 子卷的情况稍微麻烦点。如果根文件系统是 btrfs,并且 root 子卷设置得很特殊,手动加载内核时老提示找不到文件,其实不是文件不存在,而是路径没进去子卷。可以试试:
grub> insmod btrfs grub> set root=(hd0,gpt3) grub> linux /@/boot/vmlinuz-... root=/dev/sda3 rootflags=subvol=@ grub> initrd /@/boot/initrd.img-... grub> boot/@前缀是 btrfs 默认子卷的路径写法,rootflags=subvol=@是告诉内核以「@」作为 root 子卷来挂载。这个和不同发行版的默认布局强相关,建议先查好自己的子卷结构再动手。
加密分区更复杂,一般需要先从其他介质进救援系统,解锁并挂载后,进入 chroot 修复。靠 grub 命令行手动引导加密根系统,操作链太长,不建议现场硬刚,直接走 Live USB 方案反而更快。
2.4 现场急救的几个经验技巧
第一点,进了 grub 命令行,不要急着反复重启。每一次重启,你都要重新经历一遍引导失败的过程,而且有些临时状态可能还会被重置。在命令行里慢慢排查,反而最容易解决问题。
第二点,尽量用 UUID 而不是/dev/sdX设备名。设备名在 BIOS 环境、UEFI 环境、不同启动介质下,顺序可能完全不同。同一块 U 盘在某些机器上是sda,换个插口就成sdb了。UUID 是磁盘分区的唯一身份标识,Linux 内核和 GRUB 都认它。
第三点,确认内核版本时要小心。使用旧的 vmlinuz 和新的 initrd 混搭,或者反过来,有概率启动到一半崩掉。尽量选当前系统里最新、最完整的一组文件。判断是否完整,可以先分别按 TAB 看补全结果,内核文件名和 initrd 文件名版本号应该一一对应。
第四点,手动引导成功进入系统之后,别急着关机。第一件事就是执行引导修复命令,让 GRUB 配置重新生成。不然你不会想再来一遍的。
3. 修复方案:让引导恢复正常
3.1 在 grub 命令行进去系统后的一步操作
假设你已经通过手动引导进入了系统,这时候能直接在宿主机里修引导,省去很多麻烦。不同发行版生成的命令不太一样,但本质上都是同一件事:重新生成 grub.cfg。
Ubuntu 和 Debian 系:
sudo update-grubFedora 和 CentOS/RHEL 系:
sudo grub2-mkconfig -o /boot/grub2/grub.cfgArch Linux 系:
sudo grub-mkconfig -o /boot/grub/grub.cfg跑完之后,查看/boot/grub/grub.cfg或者/boot/grub2/grub.cfg是否重新生成了。如果里面能看到 Linux 内核的 menuentry 段落,说明配置已经恢复。但这里有个隐藏坑:如果系统里没有安装正确的grub-pc或者grub-efi包,重新生成配置可能失败或者生成不完整。需要先确认自己的 GRUB 版本和模式:
grub-install --version efibootmgr -v # UEFI 环境看启动项要是update-grub执行中报错,顺手查一下/boot磁盘空间是不是满了。我遇到过一台机器,boot 分区 256MB 被旧内核塞满,grub.cfg 根本写不进去,df -h一看直接 100%。清掉旧内核再更新,问题就没了。
3.2 使用 Live USB 修复的正确姿势
如果系统已经完全进不去,手动引导也失败了,那就得上 Live USB。这个方法适合任何发行版,狗屁前提条件也少:只要有一台能正常开机的电脑,做一个启动 U 盘,就能修。
Live 系统启动后,先挂载硬盘根分区:
sudo mount /dev/sda3 /mnt如果有独立 /boot 分区,继续:
sudo mount /dev/sda2 /mnt/boot如果是 UEFI 环境,必须要把 EFI 分区挂载到对应位置:
sudo mount /dev/sda1 /mnt/boot/efi挂载顺序有讲究。 /boot 和 /boot/efi 要挂在 /mnt 下面,而不是直接挂到 /mnt/boot 就完了,层级不能乱。
挂载完之后,把必要的虚拟文件系统 bind 过去,这是 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然后进入目标系统:
sudo chroot /mnt进入 chroot 之后,你就是在用目标系统的工具链了。接下来可以执行更新配置、重装引导等操作。全流程做完退出:
exit sudo umount -R /mnt sudo reboot这里有三个高频失误要特别记住。第一,忘记挂载 EFI 分区就一直折腾,grub-install 一直报错,其实是--efi-directory指向的目录是空的。第二,没有 bind 挂载/proc、/sys等虚拟文件系统,chroot 里执行硬件相关命令直接卡死或者报诡异错误。第三,修复完直接强制重启,没正常 umount,导致文件系统写缓存丢失,白修一场。
3.3 重装 GRUB 的完整差异点:BIOS 和 UEFI
在 chroot 环境下,重装 GRUB 需要根据引导模式做区分,这步绝对不能搞错。
传统 BIOS 模式,执行:
grub-install /dev/sda update-grub这里的/dev/sda是整个磁盘设备,不是某个分区。因为 GRUB 引导代码要写入 MBR,而 MBR 位于磁盘最开头,不是分区内部。
UEFI 模式,要这样:
grub-install --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=GRUB update-grub--efi-directory指定 EFI 系统分区的挂载点,--bootloader-id是自己起的引导项名称,一般叫 GRUB 或者 Ubuntu。执行成功后,EFI 分区里会生成EFI/GRUB/grubx64.efi之类的文件。
UEFI 还有个很有用的检查命令。退出 chroot 之后执行:
efibootmgr -v输出里会列出当前机器的所有启动项。确认存在类似Boot0001* GRUB ...这样的条目,并且顺序在 Windows Boot Manager 之前,才能保证下次开机先进 GRUB。如果启动项顺序不对,可以用:
efibootmgr -o 0001,0000把 GRUB 项的编号调整到第一位。
3.4 不重装也能救:手动生成最小 grub.cfg
有一种场景是 GRUB 本身安装完好,模块齐全,只是 grub.cfg 损坏或缺失。重装 GRUB 显然能解决,但如果你着急,也可以手动写一个 mini 版的 grub.cfg,把系统先拉起来再说。
手工写一个最简 grub.cfg 的模板大概长这样:
set default=0 set timeout=5 menuentry "My Linux" { insmod part_gpt insmod ext2 search --no-floppy --fs-uuid --set=root 3d4a7c6e-xxxx-xxxx-xxxx-xxxxxxxxxxxx linux /vmlinuz-6.1.0-arch1-1 root=UUID=3d4a7c6e-xxxx-xxxx-xxxx-xxxxxxxxxxxx rw initrd /initramfs-6.1.0-arch1-1.img }把 UUID 换成自己根分区的真实 UUID,内核文件名也按/boot里的实际文件修改。存到/boot/grub/grub.cfg后重启,GRUB 就能显示这个精简的启动菜单。
但需要强调,这个手写配置不具备生成系统里其他启动项的扩展能力,双系统、内核升级之后的自动更新都不会自动应用。所以这个方案主要适合「临时把系统弄起来、备份数据、安排正式修复」的阶段,正规修复还是建议走一次update-grub或者重装。
4. 那些年踩过的坑:常见误判与排查实录
4.1 "是不是数据丢了"其实是引导丢了
遇到 grub 命令行,大部分用户的第一个想法,然后告诉自己可能得重装系统。我处理过的案子里面,至少八成都是纯引导问题,盘里数据完好无损。
之前有个朋友的服务器,开机进 grub rescue,操作半天没进展,催我帮忙。我问他最近动过什么,他说插了一块新硬盘进去,然后 BIOS 把新硬盘设置成了第一启动顺序。老系统盘虽然没问题,但 MBR 引导代码指向的配置和分区 UUID 全部变了路径。解决方案非常简单,BIOS 启动顺序调整回去,一行都不改,直接开始引导。这类属于磁盘顺序变化导致的假故障,没有这个经验很难快速定位。
4.2 Windows 更新把 GRUB 顶掉了
双系统环境,Windows 更新后开机直接进 Windows,或者卡在奇怪的引导界面,是日常。原因前面提到,Windows 在更新或者修复时会重写 EFI 启动项,把 GRUB 项排在后面,甚至将原来的启动项删掉。
处理方式两种。Linux 侧:从 Linux Live USB 启动,进入 chroot 后重装 GRUB 并更新启动项顺序。也可以不进系统,直接用efibootmgr操作。比如查到了 GRUB 的项是Boot0003,执行efibootmgr -o 0003,0000设置第一启动项,重启就能看见 GRUB 菜单。Windows 侧:也可以在 Windows 命令提示符(管理员)里执行bcdedit /set {bootmgr} path \EFI\GRUB\grubx64.efi,把引导直接指向 GRUB 文件。
4.3 克隆磁盘后的引导迷局
用 dd、Clonezilla 或者一些分区克隆工具迁移系统盘,是投诉的另一个重灾区。磁盘克隆完了,盘号变了,分区比原来大了或者小了,UUID 虽然复制过来了,但 EFI 分区里的引导文件可能没被正确带到新盘上,或者 BIOS 启动顺序没有指向新盘。
有个次踩完的路径是:把旧盘的系统克隆到新 SSD,然后拔掉旧盘,开机报 grub 错误。用 Live USB 进去看,发现 EFI 分区根本没克隆到新盘上,因为克隆的时候只克隆了根分区和 boot 分区,忘了 EFI 分区(ESP)。这种只能手动把 EFI 分区复制过去,再引导修复。所以做磁盘克隆时,ESP 分区一定要包含在克隆范围里,否则事后补账很麻烦。
4.4 内核升级后 initramfs 缺失
还有一种情况是正常关机,隔天开机就直接 grub 命令行。进去一看,grub.cfg 还在,里面的 menuentry 也在,但启动时报file not found。用 ls 检查 /boot,发现 vmlinuz 引用的版本号和实际文件对不上。
这类问题大多出在「内核升级中断」。比如升级过程中空间满了,或者新内核下载一半,或者升级工具生成 grub.cfg 之后又清理了旧内核。解决方案是在 grub 命令行手动引导一个存在的内核版本,或者直接用 Live USB chroot 后重新update-grub,让它重新生成对应现有文件的配置。
4.5 grub 命令行问题快速排查表
| 现象 | 常见原因 | 快速判断方法 |
|---|---|---|
| grub rescue 模式 | GRUB 模块未加载 | ls看分区列表,找 /boot |
| grub> 模式 | grub.cfg 缺失或损坏 | ls (hd0,gptX)/boot/grub/看文件 |
启动时报file not found | 内核/initrd 版本不匹配 | 对比 vmlinuz 和 initrd 文件名 |
| Windows 更新后直接进 Windows | 启动项顺序被覆盖 | efibootmgr -v查看顺序 |
| 克隆盘后无法引导 | ESP 分区未完整克隆或 UUID 改变 | Live 检查 ESP 内容和分区 UUID |
| 开机黑屏只有光标 | 引导代码损坏或模式切换 | 用 Live USB 检查 MBR/EFI 状态 |
| 根分区是 lvm 无法启动 | 缺少 lvm 模块 | grub 里insmod lvm |
4.6 "grub minimal bash" 这句话到底在说什么
屏幕上的这句minimal bash-like line editing is supported本质上是 GRUB 在提示你:我现在处于一个简化的命令行环境,只用基本行的编辑能力,不能提供完整菜单。它不是系统崩溃,不是硬盘坏了,也不是数据清空,它只是在告诉你,GRUB 没找到配置文件,只能让你用命令行手动救。
我见过一些教程把这句话翻译成「最小 bash 式命令行编辑已可用」,单看字面没问题,但对普通用户来说毫无帮助。更准确、更有用的理解其实是:「GRUB 加载成功了,但找不到菜单配置文件,现在需要你在命令行里手动告诉它从哪启动」。说人话就是——引导程序活着,但它的菜单丢了,得你来指定启动参数。
5. 预防与应对:避免再次出现
5.1 给 GRUB 上一份保险
引导修复的功夫再熟练,也不如从源头避免问题。办法不复杂,但要坚持执行。
最简单的一层保险,是定期备份 grub.cfg。别小看这个文本文件:
cp /boot/grub/grub.cfg /boot/grub/grub.cfg.bak每次系统完成内核升级、大版本更新之后,都重新备份一次。出问题时,可以直接把备份恢复过去,至少能先启动起来。
再加一层保险,是记录关键分区 UUID:
blkid | grep -E '(/dev/sd|/dev/nvme)'把根分区、/boot 分区、EFI 分区的 UUID 记录到个人笔记里。grub 命令行里需要手填 UUID 的时候,翻笔记比自己猜要稳妥得多。
如果你用的是虚拟化环境(比如 VMware、VirtualBox),快照是成本最低的保险。做任何可能影响引导的操作之前,拍一张快照,出了问题往回一拉,几秒钟就恢复原状。物理机没有快照,那就准备一个系统救援 U 盘。我长期挂着一个 Ventoy 启动盘,里面同时塞了 SystemRescue 和 Ubuntu Live,出问题随时插上。
5.2 内核升级的正确习惯
内核升级是引导损坏的高频触发点,尤其是 Ubuntu 这种自动升级内核的发行版。
推荐养成三个习惯。第一,系统升级前先确认 /boot 分区空间充足,执行df -h /boot,留出至少两三倍的旧内核空间余量。第二,升级完成后重启前,先跑一次update-grub确认配置正确生成,再重启不迟。第三,定期清理无用的旧内核,用发行版自带工具或apt autoremove --purge处理。
如果你开启了自动安全更新,记得看看它是否包含内核更新。无脑全自动更新加自动重启,出问题你的感知窗口会非常短,可能更糟糕的是半夜里就启动不了了。
5.3 双系统用户要建立的防线
双系统用户要明确一个原则:Windows 的引导修复功能是「我很强势」的存在,只要它在磁盘上发现 Windows 分区,它就可能把引导覆盖到自己这边。
为了防止 Windows 更新把 GRUB 顶掉,可以采取两个措施。第一,在 Windows 的「禁用自动更新」策略上设置延期,至少给 Linux 侧一个缓冲时间。第二,提前学会使用efibootmgr调整启动顺序,出问题不用再折腾 Live USB,直接在 Windows 下重启到 UEFI 设置,手动选择 GRUB 启动项,一般也能进系统。
当然,如果你的 Windows 经常需要打更新,我建议把 GRUB 菜单默认超时时间调长一点,比如设置成 10 秒,这样重启的时候还有机会手动选引导项。改超时的方法:
sudo sed -i 's/GRUB_TIMEOUT=5/GRUB_TIMEOUT=10/' /etc/default/grub sudo update-grub5.4 给新手的一份实用建议
如果你刚刚接触 Linux,碰到 grub 命令行确实容易手足无措。给自己定几条底线,能减少很多损失。
第一,不在不熟悉命令的情况下直接执行rm -rf或者dd,尤其涉及全盘操作的时候。第二,不随意动分区表。看到某个分区的 UUID 变化很正常,但自己去fdisk改类型、删分区,极可能引发引导崩溃。第三,每次做可能有风险的操作前,想想数据备份问题,哪怕只是把 /etc、/boot 目录复制出来,也比没有强。
我最开始修引导的时候,也干过在 grub rescue 下误删分区的蠢事。现在修引导养成了固定习惯:先ls把所有分区列出来,再set看当前上下文,最后才动手设置参数。这个习惯帮我避开了很多不必要的坑。
根据我个人经验,grub 命令行问题百分之九十都不是灾难,而是「配置丢失」加上「专业知识不够」造成的心理恐慌。只要你理解了 GRUB 查找配置文件的路径逻辑,知道了手动引导内核这五个步骤,大部分情况都能当场解决。剩下那百分之十,交给 Live USB 和 grub-install 收尾,也足够了。
最后分享一个小技巧。grub 命令行下,TAB键真的很好用,你不需要记住完整的内核版本号,输入前缀后按 TAB,所有候选文件都会列出来。手动引导时我就是靠这个少走了很多弯路。下次再遇到minimal bash-like line editing is supported,先深吸一口气,然后按这个思路一步步来。