1. 先把引导场景摸清楚,别急着敲命令
折腾 GRUB 手动安装这件事,我这些年踩的坑比装的系统还多。很多人一上来就照着某篇教程敲grub-install /dev/sda,结果机器直接起不来,然后才开始慌。GRUB 手动安装的核心其实不是"安装"这个动作,而是先把现状摸清楚——你现在是固件模式、分区表类型、根分区和 /boot 的关系、ESP 分区在哪、目标磁盘叫什么,这五件事没弄清楚,命令敲下去就是赌博。这篇文章我按实操顺序拆开讲,从判断场景、盘点信息、理解工具分工,到 Legacy 和 UEFI 两套完整流程,再到故障现场怎么救,全部是我自己在真机上反复验证过的路径。适合已经会用 Linux 但被引导问题卡住的人,也适合想搞明白"为什么"而不是只会抄命令的朋友。
1.1 GRUB 在启动链条里到底占哪一段
一台机器从上电到看见登录界面,链条是固定的:固件(Legacy BIOS 或 UEFI)→ 引导程序 → 内核与 initramfs → init 进程 → 用户空间。GRUB 就卡在第二环,它的唯一使命是把内核和 initramfs 从磁盘上捞出来,塞进内存,然后把控制权交出去。听起来简单,但它自己又分成两半:第一段引导代码极小,Legacy 模式下塞在 MBR 后面的空隙里,UEFI 模式下就是一个.efi可执行文件;第二段才是你在菜单里看到的那个界面,它需要读取/boot/grub目录下的模块和配置文件才能干活。
这个"两段式"设计是所有问题的根源。第一段只认硬盘的物理位置,不认文件系统;第二段才认 ext4、btrfs、xfs、LVM、加密卷。所以当你搬家磁盘、改分区表、克隆系统盘的时候,第一段大概率还在原地傻等着,而它等的那个位置已经没有东西了——这就是grub rescue>出现的最常见原因。理解这一点,后面所有排查思路都是围绕"第一段能不能找到第二段"展开的。
我习惯用一句话概括:GRUB 的引导代码是"路标",/boot/grub目录是"地图册"。路标指向地图册,地图册告诉你内核在哪。路标丢了,你得重画路标;地图册过期了,你只需要重印地图册。前者是grub-install干的活,后者是grub-mkconfig干的活。这两个动作必须分开理解,混在一起就是大多数人装不明白的根本原因。
1.2 什么情况下才真的需要手动安装
不是所有引导问题都要动grub-install。我见过太多人因为菜单里少了一个内核条目,就把引导代码重写一遍,纯属给自己找事。真正需要手动安装引导代码的场景,其实就那么几类:
- 引导记录被别的东西覆盖了。装第二个系统时,对方的安装程序覆盖了 MBR 或覆盖了 ESP 里的默认引导文件,原来的菜单没了。
- 整盘克隆或迁移到新硬盘。磁盘设备名变了,UUID 有时也变了,第一段引导代码里的物理偏移全部失效。
- 分区表从 MBR 换成了 GPT,或者反过来。Legacy 模式下这个转换尤其麻烦,因为 GPT 没有 MBR 后面那 62 个扇区的"空隙"可用。
/boot或 ESP 分区被删除重建。文件系统重建了,原来的模块和配置全没了。- 自定义布局,比如根分区在 LVM 上、在加密卷里、在 btrfs 子卷里,或者
/boot单独分出来挂在别处。 - 做可移动介质,希望这套系统能在不同机器上引导。
反过来,如果只是"菜单里内核版本旧了"、"想改默认启动项"、"想加个内核参数",那只需要改/etc/default/grub然后重新生成配置,跟grub-install一点关系都没有。分清楚这两类,能省掉 80% 的无谓操作。
1.3 动手之前必须确认的三件事
我给自己定了个规矩,只要碰引导,先确认三件事,确认不了就不动手。
第一,固件模式。机器是 Legacy 启动还是 UEFI 启动?这决定了你要装i386-pc还是x86_64-efi目标,两套东西完全不通用。判断方法后面细说。
第二,目标磁盘的准确设备名。是/dev/sda、/dev/nvme0n1还是/dev/mmcblk0?注意,grub-install后面跟的是磁盘,不是分区。见过有人写grub-install /dev/sda1,直接把分区开头覆盖了,数据全废。
第三,根分区和/boot是不是分开的。这决定了--boot-directory参数该指向哪,也决定了救援时set prefix要设成什么路径。分开的情况是最容易出错的,因为很多人默认它们在一起。
提醒:这三件事在救援环境(Live 介质)里确认,而不是在已经起不来的系统上确认。系统都进不去了,你哪来的终端。
2. 信息盘点:把现状摸清再动手
救援环境起来之后,第一件事不是挂载,是观察。lsblk、blkid、fdisk -l这三条命令的输出,我一般会截图或者复制到一个文本文件里,因为后面排查全靠它。这一步花十分钟,能省后面两小时。
2.1 判断固件模式与分区表类型
判断当前启动模式最直接的办法是看/sys/firmware/efi这个目录存不存在:
# 目录存在说明当前是以 UEFI 模式启动的 ls -d /sys/firmware/efi 2>/dev/null && echo "UEFI 模式" || echo "Legacy 模式"但这里有个坑:这条命令判断的是当前这个救援环境的启动模式,不一定等于目标系统的安装模式。有些机器固件里同时开着两种兼容模式,你用 UEFI 模式做的启动盘,进去之后看到的是 UEFI,但目标系统原来是 Legacy 装的。所以还得交叉验证——看看目标磁盘上有没有 ESP 分区(类型标记为EFI System的 FAT32 分区),有的话目标系统大概率是 UEFI 装的;如果只有一根孤零零的/boot或根分区,那多半是 Legacy。
分区表类型用fdisk -l或parted -l看,输出第一行会写Disklabel type: gpt或者dos(也就是 MBR)。这个信息非常关键,因为 GPT + Legacy 的组合需要额外准备一个bios_grub分区,而 MBR + UEFI 基本是不可能组合(MBR 上虽然能放 FAT 分区,但固件通常不认)。
2.2 磁盘命名规则:新手翻车最多的地方
设备名这件事值得单独说,因为我见过太多人在这里出问题。传统 SATA、USB 盘叫/dev/sda、/dev/sdb,分区是/dev/sda1、/dev/sda2,直接加数字。但 NVMe 固态盘叫/dev/nvme0n1,分区要加个p,变成/dev/nvme0n1p1。SD 卡和 eMMC 叫/dev/mmcblk0,分区是/dev/mmcblk0p1。老式的 IDE 盘可能是/dev/hda。
| 磁盘类型 | 整盘设备名 | 分区设备名 | 注意点 |
|---|---|---|---|
| SATA / USB | /dev/sda | /dev/sda1 | 直接拼数字 |
| NVMe SSD | /dev/nvme0n1 | /dev/nvme0n1p1 | 必须带p |
| eMMC / SD | /dev/mmcblk0 | /dev/mmcblk0p1 | 必须带p |
| 虚拟磁盘 | /dev/vda | /dev/vda1 | 直接拼数字 |
为什么这个细节要命?因为grub-install /dev/nvme0n1p1这种写法,在很多版本上不会报错,它会"成功地"把引导代码写到分区的开头,然后你的分区数据就废了。而且有些老版本对 NVMe 的支持有问题,识别不到设备,得靠device.map手动指定。
我自己的习惯是,任何涉及dd、grub-install、mkfs的命令,敲完先别回车,眼睛盯着设备名再看三秒,然后lsblk对照一遍容量。这个习惯救过我至少三次。
2.3 挂载关系梳理与救援环境准备
盘清楚之后,把目标系统的分区挂起来。假设根分区是/dev/nvme0n1p3,/boot单独分出来是/dev/nvme0n1p2,ESP 是/dev/nvme0n1p1,标准挂载顺序是这样的:
# 先挂根,再挂 /boot,最后挂 ESP,顺序不能反 mount /dev/nvme0n1p3 /mnt mount /dev/nvme0n1p2 /mnt/boot mount /dev/nvme0n1p1 /mnt/boot/efi顺序为什么不能反?因为挂载是叠加的,先挂/boot/efi再挂/boot,会把前面挂的内容盖住。这个错误非常隐蔽,df -h看着一切正常,但grub-install就是找不到 ESP。
挂完之后,还要把几个虚拟文件系统 bind 进去,否则 chroot 进去之后很多工具会报错:
for d in dev dev/pts proc sys run; do mount --bind /$d /mnt/$d done/dev不挂,grub-install找不到磁盘设备;/proc和/sys不挂,一些检测逻辑会失败;/run不挂,某些发行版的脚本会卡住。这几个 bind 挂载看起来是仪式感,实际上是必需品。挂完chroot /mnt,环境才算准备完毕。
3. 两个核心工具的分工,搞混了必翻车
grub-install和grub-mkconfig是两条完全不同的命令,作用对象也不同。我把它们的关系总结成一句话:grub-install管"引导代码能不能被固件找到",grub-mkconfig管"找到之后菜单里有什么"。前者写的是磁盘的引导区域,后者写的是/boot/grub/grub.cfg这个文本文件。
3.1 grub-install 到底往磁盘上写了什么
Legacy 模式下,grub-install会做三件事:把第一段引导代码写进 MBR(前 446 字节),把核心镜像core.img写进 MBR 后面那段空隙(通常是 2048 扇区之前的那 62 个扇区里),把模块文件复制到/boot/grub/i386-pc/。UEFI 模式下简单得多:把一个.efi文件复制到 ESP 分区,然后在固件的 NVRAM 里加一条启动项。
这里有个 Legacy 模式下的经典坑:post-MBR gap(MBR 后空隙)不够大。现代分区工具默认从 1MiB 处开始分区,留出的空隙足够;但如果是旧盘或者用了某些特殊分区方案,空隙可能只有几 KB,core.img塞不进去,grub-install就会报embedding is not possible。GPT 磁盘上的 Legacy 启动更麻烦,需要单独划一个 1MiB 左右的bios_grub分区来放core.img。
--recheck这个参数我几乎每次都加,它会强制重新探测设备,忽略缓存的device.map。磁盘刚插拔过、或者在虚拟环境里设备编号变化的时候,不加这个参数经常会出现"设备不存在"的误报。
3.2 /boot/grub 目录里到底有什么
这个目录是所有 GRUB 模块的家。Legacy 模式下看i386-pc/子目录,UEFI 模式下看x86_64-efi/子目录,里面密密麻麻全是.mod文件和.lst列表文件。normal.mod是进入正常菜单界面的关键模块,ext2.mod负责读 ext 系列文件系统,lvm.mod处理逻辑卷,luks.mod处理加密卷。
除了模块,还有几个重要文件:grubenv存环境变量(下次启动进哪个条目,就记在这里),device.map是设备映射表(把(hd0)映射到/dev/sda),grub.cfg是最终生成的菜单配置。
注意:
grub.cfg是生成文件,不是手写文件。直接编辑它,下次跑grub-mkconfig就被覆盖了。要改配置请改/etc/default/grub和/etc/grub.d/下的脚本。
我见过有人在grub.cfg里手工加启动项,当时能用,内核一升级全没了,然后回来问为什么。这就是没搞清楚"生成"和"配置"的区别。
3.3 配置生成逻辑与 /etc/default/grub 里的关键项
grub-mkconfig的工作流程是:读/etc/default/grub里的默认值,然后按顺序执行/etc/grub.d/下面带可执行权限的脚本(10_linux、20_linux_xen、30_os-prober、40_custom等,数字决定顺序),把输出拼起来写到你指定的文件。
几个必须知道的配置项:
GRUB_DEFAULT:默认启动项,可以是序号、条目名,也可以是saved配合grub-set-default使用。GRUB_TIMEOUT:菜单等待秒数,设成0就是不显示菜单直接启动,设成-1是无限等待。GRUB_CMDLINE_LINUX_DEFAULT:传给内核的默认参数,quiet splash这类就在这。GRUB_DISABLE_OS_PROBER:这个默认值是true,意思是不探测其他操作系统。双系统用户最常见的抱怨"菜单里看不到另一个系统",八成就是这一项在作怪。想让它探测,得设成false,同时确认os-prober这个包已经装上。
GRUB_PRELOAD_MODULES也值得一提。如果你把根分区放在 LVM 或者加密卷上,GRUB 在早期阶段需要先加载lvm或luks模块才能读到内核。虽然grub-install通常会自己算出来,但显式写进去更保险:
GRUB_PRELOAD_MODULES="lvm part_gpt part_msdos"4. Legacy 模式的完整实操流程
假设场景:一块 MBR 分区表的硬盘/dev/sda,根分区/dev/sda2,格式 ext4,/boot独立为/dev/sda1,目标是以 Legacy 模式引导。这是最传统的布局,也是理解原理最好的切入点。
4.1 挂载、chroot 与环境校验
先从救援介质启动,按前面的顺序挂载并 bind:
mount /dev/sda2 /mnt mount /dev/sda1 /mnt/boot for d in dev dev/pts proc sys run; do mount --bind /$d /mnt/$d; done chroot /mnt /bin/bash进 chroot 之后,先确认自己真的进了目标系统,而不是还待在救援环境里。看/etc/os-release里的内容,看/boot下有没有内核文件(vmlinuz-*和initramfs-*)。如果/boot是空的,说明挂载没成功,或者内核文件已经不在了,这两种情况的处理方式完全不同。
接着确认包管理里 GRUB 相关组件还在:
# deb 系发行版 dpkg -l | grep grub # rpm 系发行版 rpm -qa | grep grub如果grub-pc或grub2这些包被误删了,得先重装包再继续。有些极端情况下/boot/grub整个目录都没了,那grub-install也会失败,因为它依赖里面的模块文件。
4.2 执行 grub-install 并读懂它的输出
Legacy 模式的标准命令:
grub-install --target=i386-pc --recheck --boot-directory=/boot /dev/sda每个参数的作用:--target=i386-pc明确指定装 Legacy 版本(在 UEFI 机器上不指定这个,默认会装 EFI 版,然后你重启发现啥也没变);--recheck强制重新探测设备;--boot-directory=/boot告诉它模块往哪拷,如果/boot没独立分区,这个参数可以省略;最后那个/dev/sda是整盘。
命令跑完,正常的输出大概是几行Installing for i386-pc platform.和Installation finished. No error reported.。重点看最后一句,没有 error 才算成功。
如果报embedding is not possible,说明 post-MBR gap 不够。这时候有两个选择:一是用--force强行装(会牺牲一部分可靠性,把核心镜像拆到多个位置),二是重新规划分区,腾出空间。我一般选前者作为临时方案,长期还是重新分区。
如果报cannot find a device for /boot/grub (is /dev mounted?),就是前面说的/dev没 bind 进去,回去补上。
4.3 生成配置并逐项校验
引导代码写完,接着生成菜单:
grub-mkconfig -o /boot/grub/grub.cfg这条命令的输出里会包含探测到的内核和操作系统列表。我通常会把输出完整看一遍,重点确认三件事:探测到了几个内核、有没有Found ... on /dev/sdaX这样的其他系统提示、有没有WARNING或error字样。
生成完毕,用grep抽查一下grub.cfg:
grep -E "menuentry|linux |initrd" /boot/grub/grub.cfg | head -30看linux那一行里的root=UUID=xxxx,这个 UUID 必须和blkid输出的根分区 UUID 一致。不一致的话,开机就会卡在Waiting for root device或者直接进救援模式。UUID 不一致通常是因为分区被重建过,或者你从另一台机器克隆过来的盘。
实操心得:
grub.cfg里的 UUID 是最容易出错的地方,克隆盘、恢复镜像、扩容分区之后都要重新核对一遍。宁可多花两分钟blkid对一遍,也别等重启之后对着黑屏发呆。
4.4 退出与重启的正确姿势
配置生成完之后,退出 chroot,按相反顺序卸载:
exit umount -R /mnt sync rebootumount -R递归卸载,把 bind 挂载一起清掉。如果报target is busy,用lsof +f -- /mnt或者fuser -vm /mnt找出占用进程。sync这一步别省,尤其是机械盘或者 U 盘上的系统,不刷盘直接重启,刚写进去的引导代码可能还没落盘。
重启之后如果看到 GRUB 菜单,说明第一段引导成功找到了第二段;如果菜单里能选中并启动系统,整个流程就算闭环了。
5. UEFI + GPT 环境的完整实操
UEFI 的流程比 Legacy 简洁,但坑点换了地方。核心差异是:引导代码不写磁盘扇区,而是以一个文件的形式放在 ESP 分区里,同时要在固件的 NVRAM 里登记一条启动项。
5.1 ESP 分区的硬性要求
ESP(EFI System Partition)的格式必须是 FAT32,分区类型标记必须是EFI System。大小方面,官方没有硬性下限,但实际上 100MiB 就开始紧张了,因为有些发行版会把内核和 initramfs 也放在 ESP 里(尤其是根分区用 btrfs 或加密卷的时候)。我一般给 512MiB 到 1GiB,够用很多年。
挂载点约定是/boot/efi,有些新方案用/efi,两种都行,关键是grub-install的--efi-directory参数要和实际挂载点对上:
mount /dev/nvme0n1p3 /mnt # 根分区 mount /dev/nvme0n1p2 /mnt/boot # 独立 /boot(如果有) mount /dev/nvme0n1p1 /mnt/boot/efi # ESP挂完之后ls /mnt/boot/efi应该能看到EFI目录(如果之前装过系统),或者至少是空目录而不是报错。如果一个空目录都没有,说明挂载失败了。
5.2 grub-install 的 UEFI 参数与 NVRAM 写入
标准命令:
grub-install --target=x86_64-efi --efi-directory=/boot/efi \ --bootloader-id=GRUB --recheck几个参数逐个说。--target=x86_64-efi对应 64 位 x86 的 UEFI 固件,ARM 机器是arm64-efi,32 位 UEFI 是i386-efi,选错目标装完固件根本不认。--efi-directory指向 ESP 挂载点。--bootloader-id决定 NVRAM 里那条启动项的名字,也决定 ESP 里EFI/下创建的子目录名。
这里有个特别需要注意的点:--bootloader-id默认值在部分发行版里是发行版名字。双系统的时候,两个系统各自的bootloader-id必须不同,否则后装的会把先装的覆盖掉。我一般统一起名叫GRUB,另一个系统叫什么随它去,反正最后靠固件启动菜单选。
装完之后验证 NVRAM 里有没有登记上:
efibootmgr -v输出里会列出所有启动项,BootCurrent是当前这个,BootOrder是启动顺序。找到GRUB那条,看它指向的路径是不是\EFI\GRUB\grubx64.efi,文件实际存不存在(去 ESP 里ls一眼)。如果 NVRAM 里没有,或者路径不对,开机就进不了 GRUB。
还有一种情况是用--removable参数。这个参数会让 GRUB 把引导文件装到EFI/BOOT/BOOTX64.EFI这个"后备路径"上,不写 NVRAM。适合做 U 盘系统,因为换机器之后 NVRAM 里的记录就失效了,但后备路径是固件一定会去查的。
5.3 Secure Boot 的坑,别硬闯
开了 Secure Boot 的机器,固件只加载有签名的引导文件。很多发行版提供的是签过名的shimx64.efi+grubx64.efi组合,正常装没问题。但如果你手动生成过 GRUB 模块,或者改过签名链,固件会直接拒绝加载,表现为开机进了固件设置界面或者黑屏,连 GRUB 菜单都看不到。
碰到这种情况,先别急着把 Secure Boot 关掉(虽然那是最快的办法),确认一下 ESP 里是不是有shimx64.efi。有的话,NVRAM 里的启动项应该指向 shim 而不是 grub 本体——shim 先被固件信任,再由它去加载 GRUB。efibootmgr -v能看到路径里带shim就对了。
提醒:自编译的 GRUB 模块、自己改过的主题、第三方内核模块,在 Secure Boot 下都会带来麻烦。做实验的时候把 Secure Boot 关掉,做完再打开,别在开着的情况下反复试。
5.4 双系统互不覆盖的实操原则
双系统最常见的痛点是"装了 B 之后 A 的引导没了"。原因通常是 B 的安装程序把 ESP 里的EFI/BOOT/BOOTX64.EFI覆盖了,或者把 NVRAM 里的启动顺序改了。
我的做法是:每个系统用自己的bootloader-id(比如GRUB-A、GRUB-B),互不干扰,开机按 F12 或是进固件菜单选。这样两个系统各自维护自己的引导,谁升级内核都不影响对方。代价是要多按一次键,但换来的是稳定。
如果非要一个菜单统管两个系统,那就得让os-prober干活。注意GRUB_DISABLE_OS_PROBER=false这个设置,还要确认os-prober包已装。有些较新的发行版默认把os-prober从依赖里移出去了,得手动装。
6. 故障现场:我遇到过的典型问题与排查路径
引导出问题的表现千奇百怪,但底层逻辑就那么几条。下面这张表是我这些年整理的高频问题速查,后面挑几个详细讲。
| 现象 | 可能原因 | 快速排查 | 处理方向 |
|---|---|---|---|
卡在grub rescue> | 第一段引导找不到第二段 | ls看能识别哪些分区 | 手动设 root 和 prefix,再insmod normal |
error: unknown filesystem | 文件系统模块没加载,或分区表变了 | 检查/boot/grub下模块是否存在 | 补模块、重设 prefix |
error: no such device | UUID 变了,设备找不到了 | blkid对比grub.cfg里的 UUID | 重新生成配置 |
| 菜单出现但选不进去 | 内核或 initramfs 路径错 | 在 GRUB 命令行cat一下路径 | 修正grub.cfg |
| 开机直接进固件设置 | NVRAM 项无效或文件不存在 | efibootmgr -v看路径 | 重装 EFI 引导 |
| 黑屏无任何输出 | 显卡驱动或终端模式问题 | 加nomodeset试 | 调内核参数 |
| 菜单里没有新内核 | 配置没重新生成 | 看grub.cfg时间戳 | 重跑grub-mkconfig |
6.1 grub rescue> 现场的救援步骤
这个提示符一出,说明第一段引导成功执行了,但它找不到normal.mod,只能停在最原始的命令行。核心思路是手动告诉它"模块在哪"。
先ls一下,看它能认出哪些(hdX,gptY)或(hdX,msdosY)组合。然后逐个试,找到能列出内容的那一个:
ls (hd0,gpt2)/ ls (hd0,gpt2)/boot/grub找到之后依次设置:
set root=(hd0,gpt2) set prefix=(hd0,gpt2)/boot/grub insmod normal normalset root指向根分区,set prefix指向模块目录。这两个设错任何一个,insmod normal都会失败。如果/boot是独立分区,prefix要指向(hd0,gpt1)/grub或者(hd0,gpt1)/boot/grub,取决于当初装的时候是怎么组织的——这也是我建议大家记一下自己的分区布局的原因。
normal执行成功后,菜单界面就回来了。这时候别急着进去,先想办法把系统启动起来,进去之后第一件事是重跑一遍grub-install,把这个临时状态变成永久状态。
6.2 unknown filesystem 和 no such device 的区别
这两个报错经常被混为一谈,但成因完全不同。
unknown filesystem是"我找到了这个分区,但我不认识它的文件系统"。原因可能是ext2.mod没加载,也可能是/boot用了 GRUB 不支持的格式(比如某些 btrfs 的子卷布局、zstd 压缩的 btrfs),还可能是分区表被改过,GRUB 读到了错误的位置。
no such device是"我要找的那个 UUID 或设备不存在了"。经典场景是整盘克隆到新硬盘,UUID 变了,或者把系统从 LVM 迁到物理分区,grub.cfg里还写着root=/dev/mapper/xxx。
区分方法很简单:unknown filesystem是路径层面的问题,用ls能列到分区但打不开内容;no such device是设备层面的问题,ls直接列不出来。前者查模块和文件系统,后者查 UUID 和设备名。
6.3 菜单里没有新内核的三类原因
升级内核之后菜单里还是旧的,这个问题我遇到过很多次,原因无非三种。
一是grub-mkconfig压根没跑。有些发行版的包管理器钩子会自动跑,有些不会,尤其是自己编译内核或者手动dpkg -i装内核包的情况。解决方法很简单,手动跑一次。
二是/boot空间满了。新内核的vmlinuz和initramfs写不进去,安装脚本静默失败或者只装了一半。df -h /boot一看就知道。清理办法是保留最近两三个内核,其余用包管理器删掉。
三是grub.cfg生成了但生成到了错误的位置。比如--boot-directory没指对,或者 chroot 环境里/boot挂载失败,配置文件写到了救援介质的/boot里,重启自然看不到。这种情况看grub.cfg的修改时间就能发现。
6.4 引导装完重启黑屏的排查顺序
黑屏是最没信息量的故障,得按顺序排除。
先看是不是固件层面的问题:开机按固件快捷键能不能进设置界面?能进说明硬件正常,问题在引导项上,回头用efibootmgr查。进不去说明连固件都没跑起来,那是硬件问题,跟 GRUB 无关。
能进固件设置但进不了 GRUB,检查 NVRAM 里的启动项路径是否正确、文件是否存在。这里面最常见的是 ESP 分区被格式化过,grubx64.efi没了,但 NVRAM 记录还在。
能看到 GRUB 菜单但选择之后黑屏,那就是内核层面的问题了。在 GRUB 菜单上按e编辑启动项,把quiet splash删掉,加上nomodeset,回车启动。如果能进系统,说明是显卡驱动的问题,进去之后装好驱动再改回来。
实操心得:调试阶段把
quiet splash去掉,让内核把启动日志全打出来,比盯着黑屏猜有用一百倍。等系统稳定了再考虑加回去。
7. 几条我踩坑之后总结的硬规矩
7.1 备份要备对地方
很多人备份 MBR 用dd if=/dev/sda of=mbr.bak bs=512 count=1,这招在 Legacy 模式下只备份了前 512 字节,也就是第一段引导代码,core.img根本没备到。真要备,得连后面那段空隙一起:count=2048。
UEFI 模式更简单,直接把整个 ESP 分区打包:tar czf esp-backup.tar.gz /boot/efi/EFI,再存一份efibootmgr -v的输出。出问题的时候,把文件解压回去,NVRAM 项重建一下,五分钟搞定。
7.2 别手工编辑生成文件
grub.cfg、grubenv之外的东西,能不手改就别手改。要加自定义启动项,写到/etc/grub.d/40_custom里,让它参与生成流程。这样内核升级、配置重生成的时候,你的自定义项还在。
/etc/default/grub才是你应该改的地方,改完统一跑grub-mkconfig。这个习惯坚持下来,能避免 90% 的"配置改了没生效"问题。
7.3 顺序很重要:先修引导还是先修系统
有个判断原则:如果系统本身能起来(哪怕是通过救援介质 chroot 进去的),就先修引导;如果系统文件已经损坏、包管理器都跑不动,那就先修系统再修引导。反过来做,经常是引导装好了,但内核和 initramfs 是坏的,还是起不来,白忙一场。
判断方法是在 chroot 里跑一次update-initramfs -u(deb 系)或dracut -f(rpm 系),能正常跑完说明系统基本健康,再动引导才安全。
最后分享一个我个人一直在用的小习惯:每次动引导之前,先在纸上或者文本文件里写下当前的分区布局、UUID、固件模式、ESP 路径,写完对照lsblk和blkid核一遍。这个动作花不了两分钟,但在我手滑敲错设备名的时候,救回来的数据价值远超这点时间。引导这东西,装对了没人记得,装错了整台机器就是块砖。