grub
GRUB
GRUB 的原始版本更名为 GRUB Legacy。GRUB Legacy 上继续进行少量维护,但最后一个版本(0.97)是在 2005 年发布的。
大约在 2007 年,GNU/Linux 发行版开始在有限的范围内使用 GRUB 2,到 2009 年底,多个主要发行版都默认安装它。
GRUB 2 (GRand Unified Bootloader version 2) 是 Linux 系统中广泛使用的引导加载器。它在操作系统启动之前运行,负责加载操作系统内核到内存,并将控制权移交给内核。理解 GRUB 2 对于系统维护、故障排除以及多系统引导至关重要。
1. GRUB 2 核心概念
GRUB 2 的设计非常模块化且强大,其核心概念包括:
多阶段引导 (Multi-stage Booting):
boot.img
(Stage 1): 位于硬盘的 MBR (Master Boot Record) 或 EFI 系统分区 (ESP) 的引导扇区。它非常小,主要任务是加载core.img
。core.img
(Stage 1.5): 包含文件系统驱动(让 GRUB 能识别各种文件系统,如 Ext4, NTFS, FAT32 等)和必要的模块。它负责找到并加载位于/boot/grub/
或/boot/grub2/
目录下的 GRUB 模块和配置文件。模块 (
.mod
文件) 和grub.cfg
(Stage 2): GRUB 的大部分功能都在这里以模块的形式存在,包括各种文件系统支持、终端、加密等。grub.cfg
是 GRUB 的主配置文件,定义了引导菜单和每个操作系统或内核的引导参数。
文件系统感知 (Filesystem Awareness): GRUB 可以直接从各种文件系统(而不仅仅是连续扇区)加载文件,这意味着您可以将内核和
initramfs
放在普通的文件系统上。引导模式 (Boot Modes):
BIOS (Legacy) 引导: 传统的引导方式,GRUB 通常安装到 MBR 或分区的引导扇区。
UEFI (Unified Extensible Firmware Interface) 引导: 现代主板使用的引导方式。GRUB 的 EFI 应用程序 (
grubx64.efi
) 放置在 EFI 系统分区 (ESP) 中,由 UEFI 固件直接调用。
配置文件生成体系: GRUB 2 的
grub.cfg
文件不推荐手动编辑。它通过一套脚本自动生成:/etc/default/grub
: 用户的全局配置,例如超时时间、默认启动项、内核参数等。/etc/grub.d/
目录下的脚本: 这些脚本按照数字顺序执行,用于检测系统上的内核、其他操作系统(通过os-prober
)并生成相应的引导条目。**40_custom
** 脚本是您添加自定义引导项的最佳位置。
GRUB Shell / GRUB Rescue: 当 GRUB 无法找到配置文件或关键文件时,它会进入一个简化的命令行界面,允许用户手动指定文件位置并尝试引导。
2. GRUB 命令行界面 (CLI)
GRUB 命令行是故障排除和高级操作的核心工具。您可以:
在 GRUB 菜单出现时,按
c
键进入 GRUB 命令行。当系统无法正常引导,进入
grub>
或grub rescue>
提示符时。
以下是 GRUB 命令行中最常用和最重要的命令:
2.1 文件系统和设备操作
ls
: 列出 GRUB 识别的设备和文件系统内容。ls
: 列出所有硬盘和分区,例如(hd0)
,(hd0,msdos1)
,(hd0,gpt1)
。ls (hd0,gpt1)/
: 列出(hd0,gpt1)
分区根目录下的内容。ls (hd0,gpt2)/boot/
: 列出(hd0,gpt2)
分区下/boot
目录的内容。用途: 用于找出您的
/boot
分区或根分区。
set
查看或设置变量。set root=(hdX,Y)
: 设置 GRUB 的根设备,这是 GRUB 查找文件(如内核、initramfs
、grub.cfg
)的起始点。hdX
表示第 X 块硬盘(从 0 开始)。Y
表示分区号,对于 MBR 分区,msdos1
是第一个主分区;对于 GPT 分区,gpt1
是第一个分区。例子:
set root=(hd0,gpt2)
表示将根设备设置为第一个硬盘的第二个 GPT 分区。
set prefix=(hdX,Y)/path/to/grub
: 设置 GRUB 模块和配置文件的路径。通常是
set prefix=(hd0,gpt2)/boot/grub
(如果/boot
是独立分区,那么(hd0,gpt2)
就是/boot
分区)。如果
/boot
是根分区的一部分,那么可能是set prefix=(hd0,gpt2)/grub
。用途: 告诉 GRUB 它的模块在哪里,以便它能加载进一步的功能。
search
查找文件/标签所在分区 search –file /vmlinuzcat
: 查看文件内容。 cat (hd0,1)/boot/grub/grub.cfg
2.2 模块加载
insmod <module_name>
: 加载 GRUB 模块。当 GRUB 进入grub rescue>
模式时,通常是因为缺少必要模块,需要手动加载。insmod normal
: 加载正常模式模块,用于显示 GRUB 菜单。insmod linux
: 加载 Linux 引导模块,以便使用linux
和initrd
命令。insmod loopback
: 加载loopback
模块,用于从 ISO 文件引导。insmod ext2
: 加载 ext2/3/4 文件系统支持模块。insmod fat
: 加载 FAT 文件系统支持模块(用于 UEFI 的 ESP)。insmod part_msdos
: 加载 MBR (DOS) 分区表支持模块。insmod part_gpt
: 加载 GPT 分区表支持模块。用途: 扩展 GRUB 的功能,使其能够识别文件系统、显示菜单或引导特定操作系统。
lsmod
: 显示已加载模块。rmmod <module_name>
: 卸载模块。rmmod ext2
2.3 引导操作系统
linux /path/to/vmlinuz [kernel_parameters]
: 加载 Linux 内核。/path/to/vmlinuz
: 这是内核文件在root
设备下的路径。例如/boot/vmlinuz-5.15.0-XX-generic
。kernel_parameters
: 传递给内核的启动参数。最常用的是root=/dev/sdXN
(指定根文件系统所在的分区) 和ro
(以只读模式挂载根文件系统)。其他常用参数有quiet
,splash
(控制启动过程的详细程度和图形界面)。例子:
linux /boot/vmlinuz-5.15.0-78-generic root=/dev/sda2 ro quiet splash
initrd /path/to/initrd.img
: 加载initramfs
(初始 RAM 文件系统)。/path/to/initrd.img
:initramfs
镜像文件在root
设备下的路径。例如/boot/initrd.img-5.15.0-XX-generic
。用途:
initramfs
包含必要的驱动和工具,以便内核能够识别硬件并挂载真正的根文件系统。
boot
: 执行之前用linux
和initrd
命令加载的内核。chainloader +1
: 用于链式加载另一个引导加载器(如 Windows 的引导管理器)。+1
表示加载当前分区(由set root
指定)的第一个扇区。用途: 引导 Windows 或其他非 Linux 操作系统。
configfile /path/to/grub.cfg
: 加载指定的 GRUB 配置文件。通常用于在 GRUB 救援模式下,手动找到并加载正确的
grub.cfg
。例子:
configfile (hd0,gpt2)/boot/grub/grub.cfg
2.4 其他常用命令
normal
: 如果prefix
和root
已正确设置且normal
模块已加载,此命令会尝试进入正常的 GRUB 菜单。exit
: 退出 GRUB 命令行,尝试继续正常启动流程或重启。reboot
: 重启系统。halt
: 关闭系统。search --file /path/to/file --set root
: 搜索包含特定文件的分区,并将其设置为root
。在不知道具体分区号时非常有用。- 例子:
search --file /boot/vmlinuz --set root
(搜索包含vmlinuz
的分区,并将其设为根)。
- 例子:
test
: 评估表达式,用于脚本调试。echo
: 在屏幕上显示消息。
除了我们之前讨论的用于文件系统和引导的核心命令 (ls
, set root
, linux
, initrd
, boot
, chainloader
, insmod
), GRUB 命令行还提供了其他功能强大的命令,用于调试、配置和特殊引导任务。
3. 变量与流程控制
GRUB 命令行不仅仅是执行命令,它还支持变量和简单的流程控制,这对于编写更复杂的引导脚本或在命令行中调试非常有用。
set <variable_name>=<value>
: 设置一个 GRUB 环境变量。这些变量只在当前会话中有效,不会持久保存。用途: 临时存储路径、文件名或引导参数。
示例:
set my_kernel_path=/boot/vmlinuz-generic
unset <variable_name>
: 取消设置一个环境变量。echo <message>
: 在屏幕上显示消息。用途: 调试或提供用户提示。
示例:
echo "Attempting to boot Linux..."
if...then...else...fi
: 条件判断语句。用途: 根据条件执行不同的引导逻辑,例如检查文件是否存在。
示例:
代码段
1
2
3
4
5
6
7
8
9
10
11if [ -f (hd0,gpt2)/boot/vmlinuz-custom ]; then
echo "Custom kernel found!"
linux (hd0,gpt2)/boot/vmlinuz-custom
initrd (hd0,gpt2)/boot/initrd.img-custom
boot
else
echo "Custom kernel not found, trying default."
linux (hd0,gpt2)/boot/vmlinuz-standard
initrd (hd0,gpt2)/boot/initrd.img-standard
boot
fi
for...in...do...done
: 循环语句。用途: 遍历列表,例如搜索特定文件。
示例:
for i in (hd0,gpt*) ; do ls $i/boot/vmlinuz ; done
(此示例语法可能因 GRUB 版本略有不同,但理念一致)
load_video
: 初始化显卡以显示图形菜单。用途: 如果 GRUB 菜单是文本模式的,加载此模块可以启用更高分辨率的图形模式,前提是你的
grub.cfg
配置了图形模式。示例:
load_video
sleep <seconds>
: 暂停执行指定的秒数。用途: 在执行某些操作前提供延迟,例如给用户阅读信息的时间。
示例:
sleep 5
4. 磁盘与分区检测
probe
: 探测设备上的文件系统或分区表。用途: 获取更多关于设备的信息,例如文件系统类型、UUID 等。
示例:
probe --fs-uuid (hd0,gpt2)
(获取分区的 UUID)probe --label (hd0,gpt2)
(获取分区的标签)
search
: 根据 UUID、文件标签或特定文件来查找分区。这是在不知道分区号时非常有用的命令。语法:
search [--file <path_to_file>] [--label <label>] [--fs-uuid <uuid>] [--set <variable_name>] [--no-floppy] [--hint-bios=<dev>] [--hint-efi=<dev>]
--set <variable_name>
: 找到后将分区路径赋值给一个变量。用途: 自动定位根文件系统或引导分区,尤其在磁盘顺序变化或使用 LiveCD 修复时。
示例:
代码段
1
2
3
4search --fs-uuid YOUR_ROOT_UUID_HERE --set root_part
linux ($root_part)/boot/vmlinuz-generic root=UUID=YOUR_ROOT_UUID_HERE ro
initrd ($root_part)/boot/initrd.img-generic
boot(你需要替换
YOUR_ROOT_UUID_HERE
为你实际的根分区 UUID,通过blkid
或ls -l /dev/disk/by-uuid/
查找)
4. 文件操作
cat <file>
: 显示文件的内容。用途: 查看
grub.cfg
、内核参数文件或任何文本文件的内容进行调试。示例:
cat (hd0,gpt2)/boot/grub/grub.cfg
cmp <file1> <file2>
: 比较两个文件。- 用途: 检查文件是否相同。
cp <source_file> <destination_file>
: 复制文件。- 用途: 在 GRUB 环境中复制文件,例如复制配置文件。
rm <file>
: 删除文件。- 用途: 清理不再需要的文件。
md_image
(raid): 用于软件 RAID 阵列。如果你的/boot
位于软件 RAID 上,这个模块是必需的。insmod md_raid0
,insmod md_raid1
,insmod md_raid5
等:加载特定 RAID 级别支持。用途: 允许 GRUB 识别并访问 RAID 卷上的文件。
5. 调试与信息
terminal_output console
/terminal_input console
: 设置 GRUB 的输入/输出终端。用途: 在进行串口调试时非常有用。
示例:
terminal_output serial
(输出到串口)
set debug=all
: 开启所有调试输出。- 用途: 当 GRUB 行为异常时,开启调试模式可以提供大量诊断信息。
clear
: 清除屏幕。help [command]
: 显示 GRUB 命令的帮助信息。用途: 学习新命令或回忆命令用法。
示例:
help linux
6. 高级引导技术
GRUB Scripting: GRUB 命令行支持的变量、条件和循环,使得你可以编写复杂的 GRUB 脚本来处理各种引导场景,远超简单的菜单选择。这在
/etc/grub.d/
下的脚本中体现得淋漓尽致。网络引导 (PXE): GRUB 可以通过网络从 PXE 服务器引导操作系统。这需要
tftp
和dhcp
模块的支持。insmod tftp
insmod net
set net_default_server=<IP>
linux (tftp)/path/to/vmlinuz
用途: 无盘工作站、大规模部署操作系统。
加密磁盘引导: GRUB 支持通过密码解锁加密的
/boot
分区或根文件系统。这涉及到cryptodisk
和luks
模块。insmod cryptodisk
insmod luks
cryptomount -u <UUID>
用途: 增强系统安全性。