我到现在都记得第一次在 grub prompt 里看到那行 grub> 时的心情:明明什么都没干,早上开个机,结果连系统登录界面都没见着,直接被丢进一个黑底白字的命令行。身边不少人遇到这种场面第一反应是“系统坏了,重装吧”,但老实说,绝大多数情况根本不需要重装。你面前这个 grub> 或者 grub rescue>,只是引导加载程序没找到配置文件,它没死,只是在等你手动把它指向正确的位置。这篇文章我就带你把这套“从 grub prompt 启动 Ubuntu”的完整逻辑和实操手法捋一遍,从最基础的命令原理到特殊分区、加密磁盘、LVM、修复加固都讲到,让以后再碰到这个界面,你敢直接上手,而不是到处找 U 盘。
1. 先搞明白:grub prompt 到底是什么状态
1.1 两种提示符,两种严重程度
很多人一看到“grub”就慌,其实第一步是先分辨你面前是哪种提示符。它们长得像,但处境完全不同:
grub>:这叫正常功能的命令行模式,能用的命令很全。这种状态通常是 GRUB 核心加载成功了,但因为它没找到grub.cfg配置文件,或者找到了但解析失败,于是原地等待你输入命令。好消息是,你的引导链其实已经走完一大半了。grub rescue>:这就严重一档。它表示 GRUB 连自己的核心模块都没能正常加载,normal.mod、linux.mod这些模块都还没进内存,所以你能用的命令被砍到只剩下ls、set、unset、insmod这几个。得先把模块路径指对,把 normal 模块加载起来,才能继续往下走。
这两种状态对应的典型原因也略有区别。grub> 多半是 /boot/grub/grub.cfg 被误删、误改名,或者配置里有语法错误;grub rescue> 则更可能是分区结构变了、GRUB 安装位置失效,或者 BIOS/UEFI 在启动时把硬盘编号搞乱了。
1.2 为什么会出现这种局面
我帮你把常见的翻车现场归一下类,方便你对号入座:
- 双系统重装 Windows:Windows 安装程序会重写 EFI 引导项,把 GRUB 的启动项顶掉,或者直接把 MBR 区域覆盖了。这是最常见的场景。
- 调整分区 / 格式化分区:之前 Ubuntu 的根分区是
/dev/sda5,你为了腾空间把分区删了重建,UUID 全变了,grub.cfg里记录的根分区 UUID 指向了不存在的分区,GRUB 找不到内核,只能掉进命令行。 - 移动硬盘 / 虚拟机设备顺序变化:同一块移动硬盘,在这台机器上是
hd0,插到另一台机器上变成hd1了;VMware 里加了块新虚拟磁盘,原来的 Ubuntu 系统盘编号也变了。GRUB 对设备编号很敏感,一旦顺序错乱就会迷路。 - /boot 被误操作:有人为了“清理空间”删了
/boot下的老内核,结果手一抖把当前内核也删了;也有人改/etc/fstab改错了根挂载点。
这种局面的本质就一句话:GRUB 自己也不知道系统在哪了,它把问题抛给了你。你只需要做一件事:用命令行告诉它“根分区在哪、内核文件在哪、initrd 在哪”。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 动手前先定位:这几个命令就是你的眼睛和手
2.1 GRUB 命令行基础命令速查
在 GRUB 的命令行里,你能用的工具很有限,但足够完成定位和启动。先记下这几条核心命令:
| 命令 | 作用 | 典型例子 |
|---|---|---|
ls |
列出所有可见设备/分区 | ls 显示 (hd0) (hd0,gpt1) ... |
set |
查看/设置环境变量 | set root=(hd0,gpt2) |
cat |
读取文件内容 | cat (hd0,gpt2)/etc/os-release |
insmod |
加载模块 | insmod normal、insmod ext2 |
search |
按特征自动查找分区 | search --no-floppy --set=root --fs-uuid 1234... |
linux |
指定内核和启动参数 | linux /boot/vmlinuz-xxx root=/dev/sda2 ro |
initrd |
指定 initrd 镜像 | initrd /boot/initrd.img-xxx |
boot |
正式启动 | boot |
这里有个容易让新手懵的地方——分区的命名规则。(hd0) 是主机上的第一块磁盘,(hd0,gpt1) 表示这块磁盘上 GPT 分区表的第一个分区;如果是传统的 MBR 分区表,显示会是 (hd0,msdos1)。中间的逗号含义是“磁盘上的第几个分区”,这个编号在 GRUB 里是从 1 开始的,注意和系统内的 /dev/sda1 一一对应,但不一定编号相同,得实际确认。
2.2 用 ls 和 cat 找到正确的根分区
在命令行敲下 ls,屏幕上会列出 GRUB 能识别的所有设备。这一步的输出就是你排查的起点。比如输出:
code复制(hd0) (hd0,gpt1) (hd0,gpt2) (hd0,gpt3)
接下来逐个分区确认。用 cat 读文件是最直接的验证方式:
code复制cat (hd0,gpt2)/etc/os-release
如果这个分区恰好是 Ubuntu 的根分区,屏幕上会出现 NAME="Ubuntu" 之类的内容;如果报错 error: file not found,就换下一个分区试。还有另一种常见做法是查看 /boot 目录:
code复制ls (hd0,gpt2)/boot
能看到 vmlinuz-... 和 initrd.img-... 文件,基本可以确定这就是 Ubuntu 安装分区,而且 /boot 没有单独划分。
这里有个小经验:如果你面对的是 grub rescue>,很多模块还没加载,cat 不一定能用。这时候可以先用 set prefix=(hd0,gpt2)/boot/grub 指对模块目录,再 insmod normal 回到完整命令行模式,再继续上面的步骤。
2.3 加载模块:insmod 的真正含义
insmod 加载的模块其实对应着对应的文件系统驱动。你要能读取 ext4 分区,就要先加载 ext2 模块(GRUB 里 ext4 和 ext2 共用这个模块);要读取 Btrfs 分区,加载 btrfs 模块;要读取 NTFS,加载 ntfs 模块。所以当你敲 insmod ext2 的时候,本质上是在告诉 GRUB:给我装上读取 ext 家族文件系统的能力。
这也是为什么在 grub rescue> 下经常要先处理 prefix 变量的原因。prefix 指向模块文件所在的目录,GRUB 需要先去那里读取 .mod 文件才能加载能力模块。如果 prefix 还是指向旧路径,那 insmod 肯定会报错找不到文件。
3. 核心操练:从 grub prompt 手动引导 Ubuntu
3.1 最稳的方法:确定根分区后逐条敲命令
当你确认了根分区是谁之后,整个手动引导就变成一条固定流水线了。假设你的根分区是 (hd0,gpt2),对应的系统内设备是 /dev/sda2,内文件名是 vmlinuz-6.8.0-50-generic 和 initrd.img-6.8.0-50-generic,那么流程就是:
code复制set root=(hd0,gpt2)
linux /boot/vmlinuz-6.8.0-50-generic root=/dev/sda2 ro quiet splash
initrd /boot/initrd.img-6.8.0-50-generic
boot
每一条命令拆开来看:
set root=(hd0,gpt2):把 GRUB 的根设备指向 Ubuntu 根分区。这里的 root 不是系统内的/,而是“从哪个分区找内核文件”。linux /boot/vmlinuz-6.8.0-50-generic root=/dev/sda2 ro quiet splash:告诉 GRUB 内核文件的位置,同时通过root=/dev/sda2告诉 Linux 内核:启动后把哪个块设备挂载为根文件系统。ro表示先以只读方式挂载根,这是 Linux 启动的标准安全做法,后面会再重新以读写方式挂载;quiet splash只是控制启动日志显示。initrd /boot/initrd.img-6.8.0-50-generic:指定 initrd 临时根文件系统镜像,它负责在真实根文件系统挂载前加载必要的驱动模块。boot:执行启动。
执行完 boot 如果一切正常,你会看到内核日志刷刷刷地滚过,然后进入熟悉的登录界面。就这么简单。
3.2 Tab 键补全:解决记不住内核版本的问题
“那我怎么记得住 vmlinuz 后面那串长长的版本号?”这个问题问得好,答案也是 GRUB 命令行里最宝贵的技巧:Tab 键自动补全。
当你打出 /boot/vmlinuz- 之后,按一下 Tab,GRUB 会自动列出该目录下所有匹配的文件名;如果只有一个,直接帮你补全。同样,initrd /boot/initrd.img- 后面也按 Tab。这比照着网上的教程手敲一长串版本号靠谱一百倍,还能顺便确认文件确实存在。
3.3 /boot 单独分区的处理方式
很多人装系统时习惯把 /boot 单独分一个区。如果遇到这种布局,根分区 (hd0,gpt2) 里是没有 /boot 目录的,所有内核文件都在 /boot 分区自己的根目录下。此时命令要改成从 /boot 分区直接指定文件:
code复制set root=(hd0,gpt3) # 假设 (hd0,gpt3) 是 /boot 分区
linux /vmlinuz-6.8.0-50-generic root=/dev/sda2 ro quiet splash
initrd /initrd.img-6.8.0-50-generic
boot
注意路径里没有了 /boot 前缀,因为当 GRUB 的 root 指向 /boot 分区时,内核文件就在这个分区的根目录下。你可以用 ls (hd0,gpt3)/ 看看里面有什么,确认 vmlinuz 和 initrd.img 是不是就在根目录。
3.4 LVM 和 LUKS 加密分区怎么办
如果你的 Ubuntu 在安装时选择了 LVM 逻辑卷管理,或者做了全盘加密(LUKS),上面的 root=/dev/sda2 就不适用了,因为真正的根文件系统在一个逻辑卷里。
先看 LVM 的情况。在 GRUB 命令行里,LVM 的逻辑卷通常会被识别成类似 (lvm/ubuntu--vg-root) 这样的设备。你需要先 insmod lvm 加载 LVM 模块,然后查看有哪些逻辑卷:
code复制insmod lvm
ls (lvm/ubuntu--vg-root)/
如果能正常列出文件,说明这个逻辑卷就是根文件系统。此时启动参数里的 root= 应该指向对应的设备映射,通常是 /dev/mapper/ubuntu--vg-root:
code复制set root=(lvm/ubuntu--vg-root)
linux /boot/vmlinuz-6.8.0-50-generic root=/dev/mapper/ubuntu--vg-root ro quiet splash
initrd /boot/initrd.img-6.8.0-50-generic
boot
再来看 LUKS 全盘加密的情况。GRUB 本身是支持 LUKS2 的(较新版本),但需要先解锁分区:cryptomount (hd0,gpt2),然后输入密码。解锁后设备会变成 (crypto0) 这样的名字,再用类似 LVM 的逻辑去定位根分区。如果在 grub prompt 里解锁不了,稳妥的做法是用 Live USB 启动后进入救援模式再处理,而不要在现场硬磕。
3.5 Btrfs 子卷的坑:别忘了 rootflags
现在很多 Ubuntu 新安装默认使用 Btrfs 文件系统,并且根目录是放在名为 @ 的子卷里的。如果只是按照普通方式指定 root=/dev/sda2,很可能会启动到一半报 Kernel panic - not syncing: VFS: Unable to mount root fs。原因就是内核找到了物理分区,但不知道要挂载 Btrfs 里的哪个子卷作为根。
解决办法是在内核参数里加上 rootflags=subvol=@:
code复制set root=(hd0,gpt2)
linux /boot/vmlinuz-6.8.0-50-generic root=/dev/sda2 ro rootflags=subvol=@ quiet splash
initrd /boot/initrd.img-6.8.0-50-generic
boot
具体子卷名是什么,可以在系统正常时执行 sudo btrfs subvolume list / 查看。默认是 @,但有些人会改成 @root 或 @ubuntu,所以别想当然。
3.6 万能替代方案:不猜分区,用 search 自动定位
如果分区太多、实在懒得一个个试,GRUB 还提供了一个自动搜索的命令 search,可以按 UUID 或文件特征定位分区。
按 UUID 搜索的前提是你知道根分区的 UUID。那在 grub prompt 里怎么知道 UUID?一种办法是如果 /etc/fstab 可读,用 cat (hd0,gpt2)/etc/fstab 就能看到根分区的 UUID。然后执行:
code复制search --no-floppy --set=root --fs-uuid 你的UUID
这样 GRUB 会把 root 变量自动设为 UUID 对应的分区。如果不想去查 UUID,也可以用文件特征搜,比如:
code复制search --no-floppy --set=root --file /etc/os-release
这个命令会遍历所有分区,找到包含 /etc/os-release 的分区,把它设为 root。搜索过程可能会有点慢,但胜在省心。注意:search 是按文件路径搜索的,前提是 GRUB 已经加载了对应分区的文件系统模块,否则它没法读取。
4. 进不了系统之后的完整救援与修复方案
4.1 从 grub rescue 恢复 normal 模式
如果你面对的是 grub rescue>,模块没加载,命令不全,但 GRUB 还是能读取磁盘的。思路是先定位 /boot/grub 目录,设置 prefix,然后加载 normal 模块回到完整模式。
code复制ls
set prefix=(hd0,gpt2)/boot/grub
insmod normal
normal
执行完 normal 后,GRUB 会尝试读取 $prefix/grub.cfg。如果这个配置文件已经损坏或缺失,你会再次进入 grub>,但没关系,现在命令全了,可以直接按第 3 节的方式手动引导。
这里对 prefix 多说两句。prefix 决定 GRUB 到哪里找它的模块文件和配置文件,它是 GRUB 自身路径的“根”。当硬盘编号变了,或者 /boot 所在分区变了,prefix 还停留在旧路径,所以 GRUB 找不到任何东西。修好 prefix,GRUB 就“找回了自己”。
4.2 进入系统后如何彻底修复引导
手动引导进入系统只是临时救急。如果你不修,下次开机又会掉回 grub prompt。进入系统后的第一步是打开终端,用 update-grub 重新生成配置文件:
code复制sudo update-grub
这个命令会扫描 /boot 下的内核、扫描其他操作系统,然后重新生成 /boot/grub/grub.cfg。很多时候这就够了,因为之前出问题就是配置文件坏了,或者里面的 UUID 过期了。
如果 update-grub 不行,或者提示找不到 GRUB 模块,那就要重新安装 GRUB 到磁盘:
code复制sudo grub-install /dev/sda
这里特别注意:grub-install 的目标是整块磁盘(比如 /dev/sda、/dev/nvme0n1),不是分区(/dev/sda1)。GRUB 需要写自己的引导代码到磁盘头部或 EFI 分区,而不是某个数据分区。填错目标可能会导致更麻烦的引导问题,一定要仔细。
4.3 系统进不去时的终极武器:Live USB + chroot
如果手动引导都进不了系统,或者说内核直接 panic 了,那常规手段就不好使了。这时候用 U 盘做一个 Ubuntu Live 环境,进去之后用 chroot 把硬盘上的系统“接管”过来修复。
大致流程如下:
code复制# 挂载根分区
sudo mount /dev/sda2 /mnt
# 如果是 EFI 启动,还要挂载 EFI 分区
sudo mount /dev/sda1 /mnt/boot/efi
# 绑定系统运行所需的虚拟文件系统
sudo mount --bind /dev /mnt/dev
sudo mount --bind /proc /mnt/proc
sudo mount --bind /sys /mnt/sys
# 进入你的系统环境
sudo chroot /mnt
进入 chroot 之后,你就好像进了原来的系统,可以执行:
code复制grub-install /dev/sda
update-grub
最后依次退出并重启:
code复制exit
sudo umount -R /mnt
sudo reboot
这个方案几乎能应对所有引导损坏场景,包括 GRUB 被 Windows 覆盖、GRUB 模块文件丢失等。唯一要注意的是 EFI 分区和 /boot 分区的挂载顺序:如果 /boot 单独分区,要先挂 /boot 再挂 /boot/efi(或者反过来,目标都是让 chroot 里的目录结构完整)。
4.4 顺手可以做的两件小事
既然是遇到了引导问题,修好之后我建议顺手做两件事,能少很多麻烦:
- 检查 /etc/fstab 里的 UUID:很多引导问题其实是 fstab 里的 UUID 写错导致的。对比
sudo blkid的输出,确保 fstab 里的每个 UUID 都对得上。 - 给 GRUB 调一下分辨率和字体:搜索热词里有人遇到“grub 字体太小”或“4k 字体”的问题。如果你用的是 4K 显示器,GRUB 默认的 640x480 分辨率下字确实小到看不清。可以在
/etc/default/grub里设置:
code复制GRUB_GFXMODE=3840x2160,1920x1080,auto
GRUB_FONT=/boot/grub/fonts/unicode.pf2
然后 sudo update-grub。这样 GRUB 菜单的字体会适配高分辨率屏幕,看起来舒服很多。
5. 常见问题与排查思路实录
我把自己这些年碰到的高频问题整理成了一张速查表,方便你卡住的时候对照:
| 现象 | 可能原因 | 处理办法 |
|---|---|---|
error: unknown filesystem |
分区文件系统模块没加载,或 GRUB 不认识这个文件系统 | insmod ext2 / insmod btrfs / insmod ntfs 等,按实际分区类型加载模块 |
error: file '/boot/vmlinuz-xxx' not found |
路径写错了,或者 /boot 是独立分区 | 用 Tab 补全确认文件名;如果是独立分区,去掉路径里的 /boot 前缀 |
Kernel panic - not syncing: VFS: Unable to mount root fs |
root= 参数指向了错误设备;LVM/Btrfs 子卷没指定 |
确认 root= 的设备路径;Btrfs 加 rootflags=subvol=@;LVM 用 /dev/mapper/... |
| 启动后黑屏,只有光标在闪 | 显卡驱动问题,尤其 N 卡 | 在内核参数里加 nomodeset,先禁用内核模式设置,进系统后再装驱动 |
error: no such device: xxx |
grub.cfg 里的 UUID 已失效 |
用 search --set=root --fs-uuid <UUID> 手动找到新分区,或进入系统后 update-grub 刷新 UUID |
secure boot 报错 / 无法启动 GRUB |
UEFI 安全启动阻止了第三方引导程序 | 进 BIOS 关闭 Secure Boot,或用 shim-signed 重新签名引导 |
5.1 启动后黑屏:加 nomodeset 参数
有个情况特别容易误判成“系统坏了”,就是内核引导没问题、initrd 也加载了,但屏幕一片黑。这种黑屏大多和显卡驱动有关,尤其是 N 卡在加载驱动时和当前内核版本不匹配。处理方式是在 grub prompt 里给内核参数加上 nomodeset:
code复制linux /boot/vmlinuz-6.8.0-50-generic root=/dev/sda2 ro nomodeset quiet splash
nomodeset 的意思是让内核不要主动切换显示模式,把显示控制留给驱动,等进入系统后再安装合适的显卡驱动。很多人手动引导成功后卡在黑屏,忘了这回事,其实是显卡驱动的小问题。
5.2 虚拟机场景(VMware/VM)的引导救援
如果你是在虚拟机里装的 Ubuntu,遇到 grub prompt 的处理思路和物理机完全相同,但有一个好用的技巧:在用 VMWare 时可以先给虚拟机加一块临时的 Live CD 镜像,启动后挂载原系统盘修复引导。设备编号变化的问题在虚拟机里更常见——比如你原来只有一块 40G 虚拟磁盘,后来为了扩容加了一块空盘,原系统盘从 (hd0) 变成 (hd1),GRUB 就找不到它了。解决办法和物理机一样,用 search --set=root --file /etc/os-release 自动定位,或手动 set root=(hd1,gpt2) 这类写法。
5.3 正常菜单启动时怎么预判参数
有个习惯帮我省了很多事:系统还能正常引导的时候,在 GRUB 菜单界面按 e 键,就能看到当前启动菜单项的完整命令列表,包括 linux 行里的所有参数。把这些参数截图或抄下来,它就变成你将来在 grub prompt 里最好的参照。你说不定会在 linux 行里发现它的 root 参数是 root=/dev/mapper/ubuntu--vg-root 或者带了 subvol 参数,这些信息在你手动引导时都是救命稻草。
5.4 分区调整后 UUID 对不上
有些朋友习惯了在 Windows 下用磁盘工具调整分区,搞完回到 Ubuntu 就进不去了。原因几乎都在 UUID 上:/etc/fstab 里写的根分区 UUID 已经不存在了,GRUB 的 grub.cfg 里记录的也是旧 UUID。这时在 grub prompt 里用 search 找到新分区、手动引导进入系统后,第一件事就是 sudo blkid 查看所有分区的新 UUID,然后修正 /etc/fstab 并 sudo update-grub。别偷懒,这一步不做干净,下次重启还会犯。
6. 写在最后的实操建议
如果让我给刚接触 Linux 的朋友一个建议:遇到 grub prompt 千万不要第一时间想着重装系统,因为手动引导的整套逻辑——定位根分区、找到内核、指定 initrd、boot——其实就构成了你对 Linux 启动过程最直观的理解。多数人花几分钟就能把系统拉起来,而且这十几条命令用熟了,以后再遇到类似的引导问题,你会从容很多。
我个人习惯是把一张“引导小抄”记在本子上或者在手机备忘录里存一份,内容包括:ls 看设备、cat (hdX,gptY)/etc/os-release 验证根分区、set root、linux /boot/vmlinuz-... root=/dev/sdaX ro quiet splash、initrd /boot/initrd.img-...、boot。每次帮别人修完引导问题,我都会把这条链路再念一遍,因为所有变种无非是在 root 参数、文件路径、文件系统模块这三个地方做文章。
最后一个非常实用的技巧:手动引导成功进入桌面后,马上执行一次 sudo update-grub 并重新启动一次,确认系统能正常进 GRUB 菜单。很多人觉得“能进系统就完事了”,结果下次开机又掉进 grub prompt,然后发现又忘了怎么处理。把“修引导”这件事一次做完,不要留尾巴。这套流程你亲手走通一遍之后,再遇到 grub> 这个提示符,它就不是拦路虎,而只是一个等你输入几条命令的普通命令行而已。
