GRUB2 引导管理器:从配置文件到修复实战
GRUB2,全称 GRand Unified Bootloader 2,是目前绝大多数 Linux 发行版的默认引导管理器。说白了,它就是操作系统启动时第一个跑起来的程序,负责把内核加载进内存。我刚开始接触多系统时,总觉得 GRUB2 很神秘,动不动就进不去系统。后来摸透了它的脾气,才发现其实就那几个核心文件在起作用。
核心认知:GRUB2 的配置文件不是手写的,而是由脚本自动生成的。你直接编辑 /boot/grub/grub.cfg ?下次更新内核,改动就全丢了。正确做法是修改 /etc/default/grub 和 /etc/grub.d/ 目录下的脚本。
GRUB2 配置文件结构
GRUB2 的配置体系分三层,我画了张图帮你理清关系:
从上图能看出来,grub.cfg 是最终产物。它由 /etc/grub.d/ 里的脚本,结合 /etc/default/grub 里的参数,通过 update-grub 或 grub-mkconfig 命令生成。我个人习惯把 /etc/default/grub 比作「调料配方」,/etc/grub.d/ 里的脚本是「菜谱步骤」,最终炒出来的菜就是 grub.cfg。
grub.cfg 详解
打开 /boot/grub/grub.cfg,你会看到一堆密密麻麻的脚本。别慌,核心结构其实很清晰:
| 段落 | 作用 | 典型内容 |
|---|---|---|
| 头部 | 加载必要模块,设置全局变量 | set default="0"、set timeout=5 |
| 菜单项 | 每个 menuentry 块定义一个启动项 |
menuentry 'Ubuntu' { ... } |
| 子菜单 | 用 submenu 包裹高级选项 |
submenu '高级选项' { ... } |
| 尾部 | 加载主题、字体等资源 | source $prefix/grub.cfg |
一个典型的 menuentry 块长这样:
menuentry 'Ubuntu 22.04 LTS' --class ubuntu --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-simple-xxxx' {
recordfail
load_video
gfxmode $linux_gfx_mode
insmod gzio
insmod part_gpt
insmod ext2
set root='hd0,gpt2'
search --no-floppy --fs-uuid --set=root xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
linux /vmlinuz-5.15.0-generic root=UUID=yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy ro quiet splash
initrd /initrd.img-5.15.0-generic
}
这里我解释几个关键点:
- set root:指定根分区,
hd0,gpt2表示第一块硬盘的第二个 GPT 分区 - search --fs-uuid:通过 UUID 查找分区,比设备名更可靠
- linux 行:指定内核文件路径和内核参数,
ro表示只读挂载根文件系统 - initrd 行:指定初始 RAM 磁盘,用于加载必要的驱动
我的经验:UUID 是分区最稳定的标识符。设备名如 /dev/sda1 会随硬盘接口变化而改变,但 UUID 不会。我曾经帮同事修一台服务器,他直接写死了 /dev/sdb2,结果加了一块硬盘后系统就起不来了。换成 UUID 后,再也没出过问题。
自定义启动菜单
想改 GRUB2 菜单?记住一个原则:改配置,别改产物。具体步骤是:
- 编辑
/etc/default/grub设置全局参数 - 在
/etc/grub.d/40_custom中添加自定义菜单项 - 运行
update-grub重新生成grub.cfg
常用的 /etc/default/grub 参数:
| 参数 | 默认值 | 说明 |
|---|---|---|
GRUB_DEFAULT |
0 | 默认启动项,可以是数字或菜单项名称 |
GRUB_TIMEOUT |
5 | 倒计时秒数,设为 -1 则等待用户选择 |
GRUB_CMDLINE_LINUX |
"" | 传递给所有 Linux 内核的额外参数 |
GRUB_DISABLE_OS_PROBER |
false | 是否禁用自动探测其他操作系统 |
GRUB_GFXMODE |
auto | 图形模式分辨率,如 1920x1080 |
举个例子,我想让 Windows 10 作为默认启动项,并且把倒计时改成 10 秒:
# 编辑 /etc/default/grub
GRUB_DEFAULT="Windows 10"
GRUB_TIMEOUT=10
# 然后更新
sudo update-grub
如果想添加一个自定义的启动项,比如从 ISO 文件直接启动:
# 编辑 /etc/grub.d/40_custom
menuentry "Live Ubuntu ISO" {
set isofile="/iso/ubuntu-22.04-desktop-amd64.iso"
loopback loop $isofile
linux (loop)/casper/vmlinuz boot=casper iso-scan/filename=$isofile quiet splash
initrd (loop)/casper/initrd
}
# 更新
sudo update-grub
注意:自定义菜单项的文件名必须以数字开头,比如 40_custom。数字决定了执行顺序,数字越小越先执行。我见过有人把文件命名为 custom,结果 update-grub 直接忽略了它。
修复 GRUB2 引导
GRUB2 坏了怎么办?别慌,我遇到过不下十次这种情况。最常见的场景是:装了 Windows 后 Linux 进不去了,或者硬盘分区表被改了。修复方法分两种:
方法一:使用 Live CD 修复(推荐)
- 用 Ubuntu Live USB 启动,选择「试用 Ubuntu」
- 打开终端,挂载根分区:
sudo mount /dev/sda2 /mnt - 挂载 EFI 分区(如果是 UEFI 模式):
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
- chroot 进入系统:
sudo chroot /mnt - 重新安装 GRUB:
# BIOS 模式
grub-install /dev/sda
# UEFI 模式
grub-install --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=Ubuntu
- 更新配置:
update-grub - 退出 chroot,重启:
exit && sudo reboot
方法二:使用 Boot-Repair 工具
如果你觉得手动操作太麻烦,可以用 Boot-Repair。它是个图形化工具,一键修复:
# 在 Live CD 中运行
sudo add-apt-repository ppa:yannubuntu/boot-repair
sudo apt update
sudo apt install boot-repair
boot-repair
选择「Recommended repair」,它会自动检测并修复 GRUB。嗯,这个工具我推荐给新手用,但作为工程师,我建议你还是学会手动修复,毕竟不是所有环境都有图形界面。
避坑指南:我曾经在修复一台服务器时,忘了挂载 /boot 分区(它是独立分区),结果 grub-install 虽然成功了,但内核文件根本没装对位置。重启后直接黑屏。记住:如果 /boot 是独立分区,一定要先挂载它。
最后说一句,GRUB2 的配置文件虽然看起来复杂,但核心逻辑就三条:别直接改 grub.cfg、用 update-grub 生成、UUID 比设备名靠谱。掌握了这三点,多系统启动的 80% 问题你都能自己搞定。