精通 GRUB 配置:实现 Linux 多系统和平共存指南

对于开发者、系统管理员和 Linux 爱好者来说,在一台计算机上安装多个操作系统(例如 Ubuntu、Arch Linux、Fedora,甚至与 Windows 共存)是一种常见需求。担任系统启动“引路人”角色的,正是 GRUB (GRand Unified Bootloader)。当多个 Linux 系统并存时,理解和管理 GRUB 配置文件变得至关重要。它不仅能让你定制化启动菜单,还能在某个系统更新或出现问题时进行修复。

本文旨在深入探讨多 Linux 系统环境下的 GRUB 配置。我们将从 GRUB 的基本结构讲起,详细解析其核心配置文件,并重点介绍如何实现多系统的自动与手动配置。无论你是刚接触多系统启动的新手,还是希望深化理解的资深用户,这篇指南都将为你提供清晰的路径。

目录#

  1. GRUB 基础:理解 GRUB 2
  2. 核心配置文件解析
  3. 多系统配置实战
  4. 常见问题与解决方案
  5. 高级技巧与最佳实践
  6. 结论
  7. 参考资料

一、GRUB 基础:理解 GRUB 2#

我们讨论的现代 Linux 发行版通常使用的是 GRUB 2(其版本号通常为 2.0x),它是早期 GRUB Legacy 的重写和升级。GRUB 2 的核心特点是模块化高度可配置性

启动流程简化为:

  1. 硬件加电自检(POST)。
  2. BIOS/UEFI 加载 GRUB 的核心镜像(core.img)。
  3. core.img 加载必要的模块,并读取 /boot/grub/grub.cfg 配置文件。
  4. 根据 grub.cfg 的配置,显示启动菜单。
  5. 用户选择或超时后,加载所选操作系统的内核并启动。

关键概念:你永远不要直接编辑 /boot/grub/grub.cfg 文件!因为这个文件是由各种工具和脚本自动生成的。直接编辑它会在你下次运行更新命令时被覆盖。

二、核心配置文件解析#

正确的配置方法是通过修改“源”文件,然后重新生成最终的 grub.cfg

2.1 /etc/default/grub:主配置#

这个文件包含了一些影响 GRUB 整体行为和外观的核心变量。

常见且重要的参数:

  • GRUB_DEFAULT=0:设置默认启动项。0 表示菜单中的第一个条目。你也可以使用菜单项的标题,例如 GRUB_DEFAULT="Ubuntu",或者使用 saved 来启动上次选择的系统。
  • GRUB_TIMEOUT=5:显示菜单的超时时间(秒)。-1 表示无限等待。
  • GRUB_CMDLINE_LINUX_DEFAULT="quiet splash":传递给 Linux 内核的默认命令行参数。例如,要禁用 NVIDIA 显卡的 nouveau 驱动,可以在此添加 modprobe.blacklist=nouveau
  • GRUB_DISABLE_OS_PROBER=false多系统的关键设置! 确保此项为 false(默认值),以允许 GRUB 在更新时自动探测其他操作系统。
  • GRUB_TERMINAL=console:强制使用控制台终端,在某些显示问题时有帮助。
  • GRUB_GFXMODE=1920x1080:设置图形模式的分辨率。

示例 /etc/default/grub

# 设置默认启动为上次选择的系统
GRUB_DEFAULT=saved
GRUB_SAVEDEFAULT=true
 
# 菜单超时 10 秒
GRUB_TIMEOUT=10
 
# 内核参数,静默启动并支持 resume(休眠恢复)
GRUB_CMDLINE_LINUX_DEFAULT="quiet splash resume=UUID=your-swap-uuid"
 
# 重要:启用 OS 探测
GRUB_DISABLE_OS_PROBER=false
 
# 设置分辨率
GRUB_GFXMODE=1920x1080

修改此文件后,需要运行 sudo update-grub(或 sudo grub-mkconfig -o /boot/grub/grub.cfg)来应用更改。

2.2 /etc/grub.d/:脚本目录#

这个目录包含了用于生成 grub.cfg 的脚本。脚本按数字顺序执行,数字决定了其在最终菜单中的位置。

  • 00_header:设置基础环境,导入 /etc/default/grub 的设置。
  • 10_linux:探测并添加当前主机上已安装的 Linux 内核。
  • 20_linux_xen:用于 Xen 虚拟化平台。
  • 30_os-prober多系统的核心脚本! 它会搜索其他硬盘分区上的操作系统(如 Windows、其他 Linux 发行版)并为它们创建菜单项。
  • 40_custom手动自定义菜单项的最佳位置。 在这里添加的配置不会在更新时被覆盖。

2.3 /boot/grub/grub.cfg:生成的最终配置#

这是 GRUB 在启动时实际读取的文件。你可以查看它来验证你的配置是否正确生效。它的结构大致如下:

...
menuentry 'Ubuntu' --class ubuntu ... {
    load_video
    insmod gzio
    ...
    linux   /boot/vmlinuz-5.15.0-xx-generic root=UUID=... ro quiet splash
    initrd  /boot/initrd.img-5.15.0-xx-generic
}

if [ "${grub_platform}" == "pc" ]; then
  menuentry "Windows 10 (on /dev/sda1)" --class windows ... {
    insmod part_msdos
    insmod ntfs
    set root='hd0,msdos1'
    chainloader +1
  }
fi
...

重申:请勿直接编辑此文件!

三、多系统配置实战#

3.1 自动探测:os-prober 的工作原理#

在大多数情况下,你不需要做任何事。当你安装完一个新的系统后,进入你想要作为主引导系统的那个 Linux,运行:

sudo update-grub

这个命令会执行 grub-mkconfig,并调用 30_os-prober 脚本。该脚本会:

  1. 扫描所有磁盘分区。
  2. 识别分区上的文件系统类型(如 ntfsext4btrfs)。
  3. 如果识别到已知的操作系统(例如在 NTFS 分区上找到 Windows 的引导文件,或在 ext4 分区上找到另一个 Linux 的内核),它会自动创建一个 menuentry

常见实践:确保 os-prober 软件包已安装(在某些最小化安装中可能没有)。

3.2 手动配置:自定义菜单项#

当自动探测失败时(例如,系统安装在特殊的存储配置上,如 LVM、软 RAID,或 os-prober 无法识别),你需要手动配置。

使用 /etc/grub.d/40_custom 文件。

示例:为 Arch Linux 添加手动菜单项

假设你的 Arch Linux 安装在 /dev/sdb3 分区,其根文件系统的 UUID 是 a1b2c3d4...

  1. 编辑 40_custom

    sudo nano /etc/grub.d/40_custom
  2. 在文件末尾添加以下内容:

    # 手动添加 Arch Linux 启动项
    menuentry "Arch Linux (Manual)" --class arch --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-simple-a1b2c3d4' {
        insmod ext4
        insmod gzio
        insmod part_msdos
        set root='hd1,msdos3'
        if [ x$feature_platform_search_hint = xy ]; then
          search --no-floppy --fs-uuid --set=root --hint-bios=hd1,msdos3 --hint-efi=hd1,msdos3 --hint-baremetal=ahci1,msdos3  a1b2c3d4...
        else
          search --no-floppy --fs-uuid --set=root a1b2c3d4...
        fi
        linux /boot/vmlinuz-linux root=UUID=a1b2c3d4... rw
        initrd /boot/initrd-linux.img
    }
    • set root='hd1,msdos3':GRUB 中磁盘从 0 开始计数。hd1 表示第二块磁盘(sdb),msdos3 表示 MBR 分区表中的第三个主分区(sdb3)。对于 GPT 分区,使用 gpt3
    • search ... fs-uuid ...:这是一个更健壮的方法,通过 UUID 来定位根分区。
    • linux /boot/vmlinuz-linux ...:指定内核路径和传递给内核的参数,其中 root=UUID=... 最重要。
    • initrd:指定初始内存盘。
  3. 保存文件,并使其可执行(有时需要):

    sudo chmod +x /etc/grub.d/40_custom
  4. 更新 GRUB 配置:

    sudo update-grub

3.3 最佳实践:为何推荐使用 40_custom#

  • 持久性40_custom 中的内容在系统更新和 grub 软件包升级时会被保留。
  • 隔离性:将自定义配置与自动生成的配置分开,便于管理和排查问题。
  • 清晰性:所有手动修改都集中在一个地方,一目了然。

四、常见问题与解决方案#

4.1 新增系统后 GRUB 菜单未更新#

  • 症状:安装新系统后,启动菜单里没有出现新系统。
  • 解决
    1. 进入你的主引导 Linux 系统。
    2. 运行 sudo update-grub,检查输出信息中是否包含类似 Found Windows Boot Manager on /dev/sda1Found Linux image: ... 的消息。
    3. 如果没有,首先确认 /etc/default/grub 中的 GRUB_DISABLE_OS_PROBER=false
    4. 尝试手动安装 os-probersudo apt install os-prober(基于 Debian/Ubuntu)或 sudo pacman -S os-prober(基于 Arch)。

4.2 Windows 系统未出现在菜单中#

这是一个非常常见的问题。

  • 原因 1:快速启动。Windows 8/10/11 的“快速启动”功能会使 Windows 分区处于一种“休眠”状态,Linux 无法安全挂载和探测。
    • 解决完全关闭 Windows(从 Windows 内部,选择“重启”而不是“关机”,因为重启会彻底关闭内核),然后再进入 Linux 运行 sudo update-grub。或者,最好在 Windows 的电源设置中永久禁用“快速启动”
  • 原因 2:安装顺序。先装 Windows,后装 Linux 是黄金法则。如果顺序反了,Windows 安装程序可能会覆盖 GRUB。
    • 解决:使用 Linux Live USB 启动,挂载你的根分区,然后 chroot 进去重装和配置 GRUB。

4.3 启动项顺序调整与默认系统设置#

  • 方法 1:修改 /etc/default/grub

    • 设置 GRUB_DEFAULT=0(数字索引)。
    • 或者设置 GRUB_DEFAULT="菜单项标题",标题必须与 grub.cfg 中的完全一致,通常用引号括起来。
    • 或者设置 GRUB_DEFAULT=saved,并同时设置 GRUB_SAVEDEFAULT=true,这样可以记住上次的选择。
  • 方法 2:使用 grub-customizer(图形化工具)。 这是一个非常方便的工具,可以调整顺序、设置默认项、修改外观等。

    # Ubuntu/Debian
    sudo add-apt-repository ppa:danielrichter2007/grub-customizer
    sudo apt update
    sudo apt install grub-customizer

    注意:虽然方便,但纯命令行操作更易于脚本化和在服务器环境下管理。

五、高级技巧与最佳实践#

5.1 美化 GRUB 界面#

可以安装主题来替换默认的蓝色界面。流行的主题如 Grub-themesCyberRe。通常步骤是下载主题包,将其复制到 /boot/grub/themes/ 目录,然后在 /etc/default/grub 中设置 GRUB_THEME="/boot/grub/themes/your-theme/theme.txt"

5.2 安全编辑:修改前的备份#

在修改任何关键配置文件前,请务必备份!

sudo cp /etc/default/grub /etc/default/grub.backup
sudo cp -r /etc/grub.d /etc/grub.d.backup

这样在出现配置错误导致无法启动时,你可以通过 Live USB 恢复。

5.3 故障恢复:使用 Live USB 重装 GRUB#

如果 GRUB 损坏,系统无法启动,你需要一个 Linux Live USB。

  1. 从 Live USB 启动。
  2. 挂载你的根分区(假设到 /mnt)和 boot/EFI 分区(如果需要)。
    sudo mount /dev/sdaX /mnt
    sudo mount /dev/sdaY /mnt/boot/efi  # 如果是 UEFI 系统
  3. 绑定必要的虚拟文件系统并 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 chroot /mnt
  4. 在 chroot 环境中重装 GRUB:
    • BIOS 系统grub-install /dev/sda(注意是磁盘,不是分区)
    • UEFI 系统grub-install --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=UBUNTU
  5. 更新 GRUB 配置:update-grub
  6. 退出 chroot,重启。

六、结论#

管理多 Linux 系统共存的 GRUB 配置,关键在于理解其模块化的工作流程:修改 /etc/default/grub 进行全局设置,利用 os-prober 实现自动探测,并通过 /etc/grub.d/40_custom 文件进行可靠的手动定制。遵循“不直接编辑 grub.cfg”和“修改前备份”的最佳实践,可以让你在享受多系统便利的同时,从容应对各种挑战。

希望这篇详细的指南能帮助你成为 GRUB 配置的高手,让你计算机上的每一个操作系统都能和谐共处,随需启动。

参考资料#

  1. GNU GRUB Manual - 官方文档,最权威的参考。
  2. Arch Wiki - GRUB - 极其详细和实用的 Wiki,适用于所有发行版。
  3. Ubuntu Wiki - GRUB 2 - Ubuntu 社区关于 GRUB 2 的指南。
  4. man grubman grub-mkconfig - 本地手册页,包含所有命令和选项的详细信息。