GRUB (简体中文)

From ArchWiki
翻译状态:本文是 GRUB翻译。上次翻译日期:2021-12-16。如果英文版本有所更改,则您可以帮助同步翻译。

GRUB ,即 GRand Unified Bootloader(大一统启动加载器),是一个 多重启动加载器,承自PUPA项目。该项目致力于开发一个新的启动加载器来取代如今叫做GRUB Legacy的启动加载器。后者已经难以维护,而 GRUB 从头重写了代码,实现了模块化和增强了移植性[1]。 如今的 GRUB 也被称作 GRUB 2,而 GRUB Legacy 表示诸0.9x版本。

注意: 在整篇文章中,esp表示EFI系统分区(即 ESP)的挂载点。

BIOS 系统

GUID分区表 (GPT) 特殊操作

BIOS/GPT配置中,必须使用 BIOS 启动分区。GRUB将core.img嵌入到这个分区。

注意:
  • 在尝试分区之前请记住不是所有的系统都支持这种分区方案,请参阅 GUID 分区表
  • 此额外分区只由 GRUB 在 BIOS/GPT 分区方式中使用。对于 BIOS/MBR 分区方式,GRUB 会把core.img放到 MBR 后面的间隙(post-MBR)中去。而在 GPT 分区表中是不能保证在第一个分区之前有这样一个可以使用的间隙的。
  • UEFI 系统也不需要这额外分区,因为它不需要嵌入启动扇区。UEFI 系统需要有EFI系统分区

安装 GRUB 前,在一个没有文件系统的磁盘上,创建一个1兆字节(使用 fdiskgdisk 和参数+1M)的分区,将分区类型设置为 GUID 21686148-6449-6E6F-744E-656564454649

  • 对于 fdisk,选择分区类型 BIOS boot
  • 对于 gdisk,选择分区类型代码 ef02
  • 对于 parted, 在新创建的分区上设置/激活 bios_grub 标记。

这个分区可以处于磁盘的前 2TB 空间中的任意位置,但需要在安装 GRUB 之前创建好。分区建立好后,按下面的命令安装启动管理器。

第一个分区之前的空间也可以用作 BIOS 启动分区,但是这会违反 GPT 对齐规范。因为这个分区不会经常访问,所以性能的影响很小,只不过有些分区工具会发出警告。可以在 fdiskgdisk 中创建一个从 34 扇区开始,一直到 2047扇区的分区,然后按照上述方式设置类型。为了让其它分区对齐,可以最后再创建此分区。

主引导记录 (MBR) 特殊操作

一般来说,如果使用兼容 DOS 的分区对齐模式,MBR 512 字节结束位置和第一个分区之间都有 31KB 的空闲空间。不过,为了提供足够的空间嵌入 GRUB 的core.img文件,建议将这个空间设置为 1 到 2 MB (FS#24103)。 建议使用支持 1 MB 分区对齐的分区软件来分区, 因为这样也能满足非 512 字节扇区磁盘分区的需求(这一点就与嵌入core.img没有关系了)。

安装

安装 软件包 grub。如果之前安装过 grub-legacyAUR,安装完成后 grub 会取代它。然后运行

# grub-install --target=i386-pc /dev/sdX

其中 /dev/sdX 是要安装 GRUB 的磁盘(不是分区),比如磁盘 /dev/sda/dev/nvme0n1或者/dev/mmcblk0,而 不是 分区 /dev/sda1,你可以查看Device file#Block device names来获得块设备命名方案的详细描述。

现在你需要 生成主配置文件

如果你的 /boot 使用了 LVM(逻辑分卷管理器),GRUB 可以安装到多个物理磁盘上。

提示: 对于安装 GRUB 的其他方式,例如安装到一个U盘上,可以参考 GRUB/Tips and tricks (简体中文)#其它安装方式

grub-install 命令的详细信息请参考 grub-install(8)GRUB 手册

UEFI 系统

注意:

安装

注意:
  • 不同硬件厂商的 UEFI 实现方式不一样,下面描述的步骤应该可以在一大类 UEFI 系统上面正常应用。对于用了下面的方法却遇到问题的用户,请将在特定的硬件上所遇到的问题的细节,以及可能的解决办法分享出来。这些案例可以添加到页面 GRUB/EFI examples (简体中文) 上面。
  • 本节假设您正在 x86_64 系统上安装 GRUB。对于 IA32 (32 位) UEFI 系统(不要和 32 位 CPU 相混淆), 将x86_64-efi替换成i386-efi

首先安装软件包 grubefibootmgr。其中“GRUB”是启动引导器,“efibootmgr”被 GRUB 脚本用来将启动项写入 NVRAM。


提示:

确保你在安装 grub你和运行指令的系统是你想用 GRUB 引导的系统。也就是说如果你是用安装介质启动进入了安装环境中,你需要在 chroot 之后再运行 grub-install。如果因为某些原因不得不在安装的系统之外运行 grub-install,在后面加上 --boot-directory= 选项来指定挂载 /boot 目录的路径,例如 --boot-directory=/mnt/boot


然后按照下列步骤安装 GRUB:

  1. 挂载 EFI 系统分区,在本节之后的内容里,把 esp 替换成挂载点。
  2. 选择一个启动引导器标识,这里叫做 GRUB。这将在 esp/EFI/ 中创建一个与标识同名的目录来储存 EFI 二进制文件,而且这个名字还会在 UEFI 启动菜单中表示 GRUB 启动项。
  3. 执行下面的命令来将 GRUB EFI 应用 grubx64.efi 安装到 esp/EFI/GRUB/,并将其模块安装到 /boot/grub/x86_64-efi/
# grub-install --target=x86_64-efi --efi-directory=esp --bootloader-id=GRUB

上述安装完成后 GRUB 的主目录将位于 /boot/grub/。注意上述例子中,grub-install 还将在固件启动管理器中创建一个条目,名叫 GRUB。-- 然而,如果你的启动条目已满,这个命令会执行失败;你需要使用 efibootmgr 来删除不必要的条目。

在配置完成后,记得#生成主配置文件

提示: 如果你使用了 --removable 选项,那 GRUB 将被安装到 esp/EFI/BOOT/BOOTX64.EFI (当使用 i386-efi 时是 esp/EFI/BOOT/BOOTIA32.EFI),此时即使 EFI 变量被重设或者你把这个驱动器接到其他电脑上,你仍可从这个驱动器上启动。通常来说,你只要像操作 BIOS 设备一样在启动时选择这个驱动器就可以了。如果和 Windows 一起多系统启动,注意 Windows 通常会在那里安装一个 EFI 可执行程序,这只是为了重建 Windows 的 UEFI 启动项。
注意:
  • --efi-directory--bootloader-id 是 GRUB UEFI 特有的。--efi-directory 替代了已经废弃的 --root-directory
  • 您可能注意到在 grub-install 命令中没有一个 <device_path> 选项,例如 /dev/sda。事实上即使提供了 <device_path>,也会被 GRUB 安装脚本忽略,因为 UEFI 启动加载器不使用 MBR 启动代码或启动扇区。

如果遇到问题,查看 UEFI 故障排查。参见GRUB/Tips and tricks (简体中文)#UEFI 延伸阅读

配置

完成安装之后,GRUB 在每次启动的时候载入配置文件 /boot/grub/grub.cfg。你可以使用工具来#生成 grub.cfg,或者可以手动#定制 grub.cfg

生成 grub.cfg

本节只讲述如何编辑配置文件 /etc/default/grub。更多信息请见 GRUB/Tips and tricks (简体中文)

请记住,每当修改 /etc/default/grub 或者 /etc/grub.d/ 中的文件之后,都需要再次生成主配置文件

生成主配置文件

安装后,需要生成主配置文件 /boot/grub/grub.cfg。配置文件的生成过程受到 /etc/default/grub 中的选项和 /etc/grub.d/ 下脚本的影响。

如果你没有进行额外配置,自动生成程序会在当前启动的系统的根文件系统中侦测配置文件。所以请确保系统已经启动或者已经通过 chroot 进入。

注意:
  • 请记住,每当修改 /etc/default/grub 或者 /etc/grub.d/ 中的文件之后,都需要再次生成 /boot/grub/grub.cfg
  • 默认的文件路径是 /boot/grub/grub.cfg,而非 /boot/grub/i386-pc/grub.cfg
  • 如果你是在 chroot 或者 systemd-nspawn 容器中运行 grub-mkconfig,可能会报 grub-probe 无法获取 "canonical path of /dev/sdaX" 错误而无法正常执行。此时可以尝试使用 arch-chroot,参见 BBS post
  • 如果你在使用了 LVM 的 chroot 环境中安装 GRUB,grub-mkconfig 会无限期挂起。参见 #Device /dev/xxx not initialized in udev database even after waiting 10000000 microseconds

使用 grub-mkconfig 工具来生成 /boot/grub/grub.cfg

# grub-mkconfig -o /boot/grub/grub.cfg

自动生成脚本默认将在生成的配置文件中为所有已安装的 Arch Linux 内核添加一个条目。

提示:

如果想要自动为其他操作系统添加条目,请见#探测其他操作系统

如果想要添加自定义条目,你可以编辑 /etc/grub.d/40_custom 文件,然后重新生成 /boot/grub/grub.cfg。或者你可以创建 /boot/grub/custom.cfg 文件然后把条目添加进这里面。修改 /boot/grub/custom.cfg 文件后不用再运行 grub-mkconfig 程序,因为 /etc/grub.d/41_custom 文件已经在生成的主配置文件中添加了相关的 source 语句来引用 /boot/grub/custom.cfg

提示: /etc/grub.d/40_custom 可以用做创建 /etc/grub.d/nn_custom 文件的模板,其中 nn 为优先级,规定脚本文件的执行顺序。而脚本文件的执行顺序决定了其所添加的条目在 GRUB 启动菜单中的位置。nn 应当比 06 大,以此保证重要的脚本能够优先执行。

如要参考自定义菜单条目的例子,请看#启动菜单条目示例

探测其他操作系统

想要让 grub-mkconfig 探测其他已经安装的系统并自动把他们添加到启动菜单中,安装 软件包 os-prober挂载 包含其它系统的磁盘分区。然后重新运行 grub-mkconfig。如果你得到以下输出:Warning: os-prober will not be executed to detect other bootable partitions,你需要编辑/etc/default/grub并取消下面这一行的注释,如果没有相应注释的话就在文件末尾添加上:

GRUB_DISABLE_OS_PROBER=false

然后运行 grub-mkconfig 再试一次。

注意: 记得每次运行 grub-mkconfig 之前都把包含其他操作系统的分区挂载上,以免忽略了这些操作系统的启动项。
提示: 你可能想让grub记住你上次选择的启动项,参见GRUB/Tips and tricks (简体中文)#调用之前的启动条目
MS Windows

os-prober 通常能自动发现包含 Windows 的分区。当然在载入默认的 Linux 驱动的情况下,NTFS 分区也不是总能够被探测到。如果 GRUB 没能发现它,尝试安装 NTFS-3G,然后重新挂载这个分区再试一次。

加密的 Windows 分区需要在解密之后才能挂载。对于 BitLocker,可以使用 dislockerAUR。这足够 os-prober 来添加正确的启动条目了。

额外的参数

如想为 Linux 镜像添加额外的参数,你可以在 /etc/default/grub 中设置 GRUB_CMDLINE_LINUXGRUB_CMDLINE_LINUX_DEFAULT 变量。生成普通启动项时,这两个参数的值会合并在一起传给内核。生成 recovery 启动项时, 仅使用 GRUB_CMDLINE_LINUX 参数。

两个参数不是一定要一起用。例如要系统支持休眠后恢复,可以使用 GRUB_CMDLINE_LINUX_DEFAULT="resume=UUID=uuid-of-swap-partition quiet",其中 uuid-of-swap-partition 是你的交换分区的 UUID。这样在生成 recovery 启动项时,将不会启用 resume 功能,也不会有 quiet 参数来省略启动时的内核信息。而其他的普通启动项会包含它们。

grub-mkconfig 默认使用根文件系统的 UUID,要禁用此设置,取消 GRUB_DISABLE_LINUX_UUID=true 前的注释。

要生成 GRUB recovery 启动项,需要确保在 /etc/default/grubGRUB_DISABLE_RECOVERY 没有设置为 true

更多信息请参考Kernel parameters (简体中文)

LVM

Merge-arrows-2.pngThis article or section is a candidate for merging with #安装.Merge-arrows-2.png

Notes: grub-mkconfig 能自动检测是否需要 lvm 模块,没有必要专门在GRUB_PRELOAD_MODULES 中标明。将警告移动到#安装 & #Installation_2 或创建一个Known issues section 并在里面写明。 (Discuss in Talk:GRUB (简体中文))
警告: GRUB 不支持 thin-provisioned 逻辑卷。

如果你的 /boot 或者 / 分区使用了 LVM,确保 lvm 模块已经预先加载好。

/etc/default/grub
GRUB_PRELOAD_MODULES="... lvm"

阵列

Merge-arrows-2.pngThis article or section is a candidate for merging with #安装.Merge-arrows-2.png

Notes: grub-mkconfig 能自动检测是否需要 mdraid09 以及 mdraid1x 模块,不需要在 GRUB_PRELOAD_MODULES 里面标明。将两个 grub-install 写到一个注意事项里,然后把它移动到#安装;将那些 set root 语句转移到 #定制 grub.cfg。 (Discuss in Talk:GRUB (简体中文))

GRUB 可以很方便地操作 RAID 卷,你只需加载 GRUB 模块 mdraid09 或者 mdraid1x 就可以像其他卷一样进行操作了。

/etc/default/grub
GRUB_PRELOAD_MODULES="... mdraid09 mdraid1x"

例如 /dev/md0 写成:

set root=(md/0)

而 RAID 卷上的分区(如 /dev/md0p1)则是:

set root=(md/0,1)

如要在 /boot 分区使用 RAID1 时(或者 /boot 位于使用了 RAID1 的根分区之中)安装 GRUB,对于 BIOS 系统,直接在各个驱动器上运行 grub-install 即可,就像这样:

# grub-install --target=i386-pc --debug /dev/sda
# grub-install --target=i386-pc --debug /dev/sdb

上例中 /boot 所在的 RAID 1 序列位于 /dev/sda/dev/sdb 上。

注意: GRUB 支持从 Btrfs RAID 0/1/10 启动,但 不支持 RAID 5/6。对 RAID 5/6,你可以使用 mdadm,这个 GRUB 是支持的。

/boot 加密

GRUB 还专门支持从加密的 /boot 启动。这需要解锁一个 LUKS 块设备,来读取配置文件以及载入 initramfs内核。这个选项试图解决未加密的 boot 分区问题。

提示: /boot 不需要 专门放到一个单独的分区,它也可以就留在系统的根目录 / 下面。
警告: GRUB 2.0.6 仅对 LUKS2 headers 提供了有限的支持,参见 GRUB bug #55093
  • Argon2i (cryptsetup default) 与 Argon2id PBKDFs 是不受支持的,但是 PBKDF2 可以.
  • grub-mkimage/grub-install 不支持创建一个可以解密 LUKS2 的镜像。请查看grub-gitAUR下方的评论以获得详细信息。

要启用这个功能,正常使用 LUKS/boot 所在的分区加密,然后在 /etc/default/grub 中添加如下选项:

/etc/default/grub
GRUB_ENABLE_CRYPTODISK=y

grub-install 使用这个选项来生成 core.img,所以在修改这个选项之后要重新安装 grub

如果没有进一步的修改,你需要两次输入一个密码:第一次是为了让 GRUB 在启动伊始解锁 /boot 的挂载点,第二次是在 initramfs 的要求下解锁根文件系统。你可以用 keyfile 来避免密码输入过程。

警告:
  • 如果你想要 生成主配置文件,确保 /boot 已经挂载好了。
  • 为了进行与 /boot 的挂载点有关的系统更新,确保在进行更新之前已经对加密的 /boot 进行了解锁和挂载。如果使用了独立的 /boot 分区,这个可以通过使用 crypttab 和一个 keyfile 在启动的时候自动完成。
注意:
  • 如果你使用了特别的键盘映射,默认安装的 GRUB 是不知道的。这关系到如何输入密码来解锁 LUKS 块设备。请查阅 GRUB/Tips and tricks (简体中文)#为早期启动手动配置核心映像
  • 如果你遇到问题没法显示输入密码的界面(与 cryptouuid, cryptodisk相关的错误,或者 "device not found"),可以试着重新安装 GRUB,并在 grub-install 命令的尾部加上 --modules="part_gpt part_msdos"
提示: 你可以使用 pacman hooks 来在升级时涉及到 /boot 中的文件的时候自动挂载它。

定制 grub.cfg

Tango-view-fullscreen.pngThis article or section needs expansion.Tango-view-fullscreen.png

Reason: 添加指导如何编写一个定制的 /boot/grub/grub.cfgUser:Eschwartz/Grub 中有一个草稿可以查阅。 (Discuss in Talk:GRUB (简体中文)#Manually generate grub.cfg)

这一节讲述如何在 /boot/grub/grub.cfg 中手工创建 GRUB 启动条目,而非使用 grub-mkconfig。

基础的 GRUB 配置文件使用如下的设置:

  • (hdX,Y) 为磁盘 X 上的分区 Y,分区编号从 1 开始,磁盘编号从 0 开始。
  • set default=N 为在用户选择时间内没有进行选择时的默认启动条目。
  • set timeout=M 即在使用默认条目启动前,等待用户自行选择的时间为 M 秒。
  • menuentry "title" {entry options} 为一个标题为 title 的启动条目。
  • set root=(hdX,Y) 设置 \boot 分区,即内核和 GRUB 模块存储的位置。(\boot 不一定要位于一个独立的分区,可能是根分区(/) 下面的一个目录。)

启动菜单条目示例

提示: 在使用由 grub-mkconfig 所生成的 /boot/grub/grub.cfg 时,这些启动条目仍然是可以用的。将它们添加到 /etc/grub.d/40_custom 中然后重新生成主配置文件,或者将它们添加到 /boot/grub/custom.cfg中。

若要管理多个 GRUB 条目,比如既使用 linux 又使用 linux-lts 内核,相关的提示可以参见 GRUB/Tips and tricks (简体中文)#多个启动条目

对于 ArchisoArchboot 启动菜单条目,参见 Multiboot USB drive#Boot entries.

GRUB 命令
"关机" 菜单项
menuentry "System shutdown" {
	echo "System shutting down..."
	halt
}
"重启" 菜单项
menuentry "System restart" {
	echo "System rebooting..."
	reboot
}
"UEFI固件设置" 菜单项
if [ ${grub_platform} == "efi" ]; then
	menuentry 'UEFI Firmware Settings' --id 'uefi-firmware' {
		fwsetup
	}
fi
EFI 可执行文件

在启用了 UEFI 模式时,GRUB 可以 chainload 其它 EFI 可执行文件。

提示: 如要让这些启动条目仅在 GRUB 处于 UEFI 模式的时候显示,只需把它们放到下面的 if 语句中:
if [ ${grub_platform} == "efi" ]; then
	放入仅 UEFI 显示的启动条目
fi
UEFI Shell

要启动 UEFI Shell,你可以将它放在 EFI 系统分区的根目录里,然后添加如下菜单条目:

menuentry "UEFI Shell" {
	insmod fat
	insmod chain
	search --no-floppy --set=root --file /shellx64.efi
	chainloader /shellx64.efi
}
gdisk

下载 gdisk EFI application 然后复制 gdisk_x64.efiesp/EFI/tools/

menuentry "gdisk" {
	insmod fat
	insmod chain
	search --no-floppy --set=root --file /EFI/tools/gdisk_x64.efi
	chainloader /EFI/tools/gdisk_x64.efi
}
Chainload 一个统一的内核镜像

如果你有一个按照 Secure Boot 或者其他方法生成的 .efi 文件,你可以把它添加到启动菜单里。例如:

menuentry "Arch Linux " {
	insmod fat
	insmod chain
	search --no-floppy --set=root --fs-uuid FILESYSTEM_UUID
	chainloader /EFI/Linux/Arch-linux.efi
}
多系统启动
GNU/Linux

假设另一个发行版位于 sda2

menuentry "Other Linux" {
	set root=(hd0,2)
	linux /boot/vmlinuz (add other options here as required)
	initrd /boot/initrd.img (if the other kernel uses/needs one)
}

或者让 GRUB 根据 UUID 或文件系统标签查找正确的分区:

menuentry "Other Linux" {
        # 假设 UUID 为 763A-9CB6
	search --no-floppy --set=root --fs-uuid 763A-9CB6

        # 按照 label OTHER_LINUX 来搜索(确保分区 label 是精确的)
        #search --no-floppy --set=root --label OTHER_LINUX

	linux /boot/vmlinuz (按需求在这里添加其他的选项,例如: root=UUID=763A-9CB6 )
	initrd /boot/initrd.img (如果其他的内核需要的话)
}

如果其他发行版已经有一个有效的/boot文件夹,并安装了GRUB、grub.cfg、kernel和initramfs,可以指示GRUB在启动时即时加载这些其他grub.cfg文件。例如,对于hd0和第四个GPT分区:

menuentry "configfile hd0,gpt4"  {
    insmod part_gpt
    insmod btrfs
    insmod ext2
    set root='hd0,gpt4'
    configfile /boot/grub/grub.cfg
}

选择此条目时,GRUB会从另一卷加载grub.cfg文件并显示该菜单。在configfile返回后,文件中的命令所做的任何环境变量改变将不会被保留。按Esc返回到第一个GRUB菜单。

UEFI/GPT 模式下安装的 Windows

这个模式寻找 Windows 的启动加载器的位置,然后当用户选择了相应的菜单条目的时候,通过链式载入的方法在 GRUB 之后加载它。这里主要的任务是找到 EFI 系统分区然后从上面运行启动加载器。

注意: 这个启动项仅在 UEFI 模式下才起作用,而且 Windows 和 UEFI 的位数必须相同。如果 GRUB 是 BIOS 模式,这个方法无效。参考 Dual boot with Windows#Windows UEFI vs BIOS limitationsDual boot with Windows#Bootloader UEFI vs BIOS limitations
if [ "${grub_platform}" == "efi" ]; then
	menuentry "Microsoft Windows Vista/7/8/8.1 UEFI/GPT" {
		insmod part_gpt
		insmod fat
		insmod chain
		search --no-floppy --fs-uuid --set=root $hints_string $fs_uuid
		chainloader /EFI/Microsoft/Boot/bootmgfw.efi
	}
fi

其中 $hints_string$fs_uuid 由下述两个命令得到。

$fs_uuid 命令检测 EFI 系统分区的 UUID:

# grub-probe --target=fs_uuid esp/EFI/Microsoft/Boot/bootmgfw.efi
1ce5-7f28

或者你可以(以 root 身份)运行 blkid 然后从结果中找到 EFI 系统分区的 UUID。

$hints_string 命令可以确定 EFI 系统分区的位置,在当前的例子中是 harddrive 0:

# grub-probe --target=hints_string esp/EFI/Microsoft/Boot/bootmgfw.efi
--hint-bios=hd0,gpt1 --hint-efi=hd0,gpt1 --hint-baremetal=ahci0,gpt1

这两个命令都是假设 Windows 使用的 ESP 是挂载在$esp上的。当然,Windows的 EFI 文件路径可能有变,因为这就是Windows....

BIOS/MBR 模式下安装的 Windows
注意: GRUB 支持直接启动 bootmgr,如今启动 BIOS/MBR 模式下安装的 Windows 时不再需要链式加载分区启动扇区了。
警告: bootmgr 位于系统分区(system partition),而不是 Windows 系统所在的分区(通常为 C: 盘)。系统分区的文件系统标签System Reserved 或者 SYSTEM 而且这个分区的容量只有大概 100 到 549 MB。详情参考 Wikipedia:System partition and boot partition

本节假设你的 Windows 分区是 /dev/sda1。如果分区不同,需要对每一处 hd0,msdos1 进行修改。

注意: 这些菜单条目仅在 BIOS 启动模式下可用,不能在 UEFI 模式下安装的 GRUB 上使用。参考 Dual boot with Windows#Windows UEFI vs BIOS limitationsDual boot with Windows#Bootloader UEFI vs BIOS limitations

在所有例子里,XXXXXXXXXXXXXXXX是指文件系统的 UUID,可以通过 lsblk --fs 命令得到。

对于 Windows Vista/7/8/8.1/10:

if [ "${grub_platform}" == "pc" ]; then
	menuentry "Microsoft Windows Vista/7/8/8.1/10 BIOS/MBR" {
		insmod part_msdos
		insmod ntfs
		insmod ntldr     
		search --no-floppy --fs-uuid --set=root --hint-bios=hd0,msdos1 --hint-efi=hd0,msdos1 --hint-baremetal=ahci0,msdos1 XXXXXXXXXXXXXXXX
		ntldr /bootmgr
	}
fi

对于 Windows XP:

if [ "${grub_platform}" == "pc" ]; then
	menuentry "Microsoft Windows XP" {
		insmod part_msdos
		insmod ntfs
		insmod ntldr     
		search --no-floppy --fs-uuid --set=root --hint-bios=hd0,msdos1 --hint-efi=hd0,msdos1 --hint-baremetal=ahci0,msdos1 XXXXXXXXXXXXXXXX
		ntldr /ntldr
	}
fi
注意: 在某些情况下,可能在安装 Windows 8 之前就已经安装了GRUB。启动 Windows 时可能会出现\boot\bcd 报错(错误代码为 0xc000000f)。要修复这个问题,可以进入 Wondows Recovery Console(安装磁盘中的 cmd.exe)然后运行:
X:\> bootrec.exe /fixboot
X:\> bootrec.exe /RebuildBcd

不要 使用 bootrec.exe /Fixmbr,因为那会将 GRUB 清除掉。或者你可以用 Troubleshooting 菜单里的 Boot Repair 函数,它不会清除 GRUB 而且可以修复大部分错误。而且最好是保证连接电脑的介质 只有 目标硬盘和你的可启动介质,如果你连接了其他的设备,Windows 很可能会没法修复启动信息。

使用标签

通过使用search--label选项,可以使用人类易于阅读的文件系统标签。首先请确保你的文件系统有唯一标签

然后你就可以使用标签来添加一个条目:

menuentry "Arch Linux, session texte" {
  search --label --set=root archroot
  linux /boot/vmlinuz-linux root=/dev/disk/by-label/archroot ro
  initrd /boot/initramfs-linux.img
}


使用 GRUB 命令行

MBR 太小,不足以存储所有的 GRUB 模组,所以 MBR 里面只有启动目录和一些很基本的命令。GRUB 的主要功能通过 /boot/grub 里的模组实现,按需加载。出现错误时,GRUB 可能不能引导启动(比如磁盘分区发生了变化)。这时候,一般会出现命令行界面。

GRUB 不止提供一个 shell,如果 GRUB 不能读取到启动目录配置,但是能找到磁盘,你很可能会进入 "正常" shell:

grub>

如果有更严重的问题(比如 GRUB 找不到必须的文件了),GRUB 就可能会让你进入 "救急" shell:

grub rescue>

救急模式下的 shell 是正常 shell 的一个严格的子集,其支持的功能更少。如果不幸进入了救急模式的 shell 里,首先尝试加载 normal 模块,然后启动正常 shell:

grub rescue> set prefix=(hdX,Y)/boot/grub
grub rescue> insmod (hdX,Y)/boot/grub/i386-pc/normal.mod
rescue:grub> normal

分页支持

GRUB 支持对长输出进行分页(比如运行 help 的输出)。不过只能在正常 shell 中支持,在救急 shell 中则不支持。开启分页支持需要在 GRUB 命令行中键入:

sh:grub> set pager=1

使用命令行引导操作系统

grub> 

可以使用 GRUB 命令行引导操作系统,一个典型的应用场景是通过“chainloading”来引导储存在一个驱动器或者分区中的 Windows 或 Linux 系统。

ChainLoading 的意思是用当前的启动加载器去载入另一个启动加载器,所以叫做链式加载。

要被加载的另一个启动加载器可能嵌入在一个有分区表的磁盘的头部 (MBR),或在一个未分区磁盘或者一个分区的头部 (VBR),也可能在使用 UEFI 的情形下是一个 EFI 可执行文件。

链式加载一个分区的 VBR

set root=(hdX,Y)
chainloader +1
boot

X=0,1,2... Y=1,2,3...

比如链式加载一个位于首磁盘,首分区上的 Windows:

set root=(hd0,1)
chainloader +1
boot

同样也可以使用 GRUB 链式加载另一个分区引导扇区上的 GRUB。

链式加载磁盘的 MBR 或未分区磁盘的 VBR

set root=hdX
chainloader +1
boot

链式加载 UEFI 模式下安装的 Windows/Linux

insmod fat
set root=(hd0,gpt4)
chainloader (${root})/EFI/Microsoft/Boot/bootmgfw.efi
boot

insmod fat 用来加载 FAT 文件系统模块,以访问 EFI 系统分区上的 Windows 启动加载器。 (hd0,gpt4)/dev/sda4 是该示例中的 EFI 系统分区。 chainloader 一行中的条目用来指定需要被链式加载的 .efi 文件。

正常载入

请参考#使用救急控制台中的例子。

使用救急控制台

请先阅读#使用 GRUB 命令行。如果无法进入正常的命令行,请尝试使用 Live CD 或者其他救急磁盘引导,然后修正配置错误,重新安装 GRUB。不过有些时候我们手上没有此类救急磁盘,这时救急控制台就可以派上用场了。

GRUB 应急控制台里可用的命令有 insmodlssetunset。这个例子里用了 setinsmodset 用来修改变量,insmod 用来载入模组以添加功能。

首先,用户必须知道启动分区 (/boot) 所在位置(是一个独立的分区或者是根目录下的子目录),然后设置:

grub rescue> set prefix=(hdX,Y)/boot/grub

其中 X 是物理驱动器的编号,而 Y 是分区的编号。

注意: 如果启动分区是个独立的分区,要在路径中省略 /boot(例如键入 set prefix=(hdX,Y)/grub)。

通过加载 linux 模组来扩展命令行的功能:

grub rescue> insmod i386-pc/linux.mod

或者直接

grub rescue> insmod linux

这个模组会启动对我们熟悉的 linuxinitrd 命令的支持。

比如要启动 Arch Linux:

set root=(hd0,5)
linux /boot/vmlinuz-linux root=/dev/sda5
initrd /boot/initramfs-linux.img
boot

如果 /boot 在单独分区上(例如在用 UEFI 的时候),适当地进行修改:

注意: 因为 boot 是一个单独的分区而不是根分区的一部分,你得手动把它的地址写清楚,格式和前面的 prefix 一样。
set root=(hd0,5)
linux (hdX,Y)/vmlinuz-linux root=/dev/sda6
initrd (hdX,Y)/initramfs-linux.img
boot
注意: 如果你在执行 linux 命令的时候遇到了 error: premature end of file /YOUR_KERNEL_NAME,你可以尝试用 linux16 来替代。

成功启动 Arch Linux 后,用户可以修正 grub.cfg 然后重新安装 GRUB。

为了完全修正错误和重新安装 GRUB,可能需要修改 /dev/sda。详情请参考#安装(BIOS)或者#安装_2(UEFI)章节。

GRUB removal

Tango-view-fullscreen.pngThis article or section needs expansion.Tango-view-fullscreen.png

Reason: 从 BIOS 启动迁移到 UEFI 不是需要移除 GRUB 的唯一例子。本节要么需要包含如何移除为 UEFI 启动安装的 GRUB,要么就应当被删除掉,因为它实在太简短了。 (Discuss in Talk:GRUB (简体中文))

在迁移到 GPT/UEFI 后,你可能想要移除 MBR 启动代码,只需 使用 dd:

# dd if=/dev/zero of=/dev/sdX bs=440 count=1

疑难解答

不支持的文件系统

GRUB 不支持 F2FS 文件系统。如果根目录分区是一个不支持的文件系统,那就需要为 /boot 单独分区,并使用一个支持的文件系统。某些情况下,GRUB 的开发版 grub-gitAUR 可能已经支持了那个文件系统。

如果将 GRUB 和一个不支持的文件系统一起用,它将无法提取到你的驱动器的 UUID,只能使用传统的名称 /dev/sdXx 来代替,而这个名称是可能会变化的。此时你可能需要手动编辑 /boot/grub/grub.cfg,将 root=/dev/sdXx 改为 root=UUID=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX。你可以使用 blkid 命令来获取你的设备的 UUID ,参见 Persistent block device naming (简体中文)

启用调试信息

注意: 每当你#生成主配置文件的时候,这个设定就会被覆盖掉。

grub.cfg 中添加:

set pager=1
set debug=all

出现 “msdos-style” 错误消息

grub-setup: warn: This msdos-style partition label has no post-MBR gap; embedding will not be possible!
grub-setup: warn: Embedding is not possible. GRUB can only be installed in this setup by using blocklists.
            However, blocklists are UNRELIABLE and its use is discouraged.
grub-setup: error: If you really want blocklists, use --force.

这个错误可能当你在 VMware 容器里面安装 GRUB 的时候出现。请阅读相关链接。这种情况是因为首分区直接从 MBR 后开始(即第 64 个扇区),而不是和正常的那样在 MBR 后面有 1MB(2048个扇区)的间隙。请参阅#主引导记录 (MBR) 特殊操作

UEFI 异常

常见安装错误

  • 如果你在将 sysfs 或者 procfs 与 grub-install 一起使用的时候,遇到要求你必须运行 modprobe efivarfs 的问题,尝试 Unified Extensible Firmware Interface (简体中文)#挂载 efivarfs
  • 如果不用 --target 或者 --directory 选项,grub-install 不知道应该安装哪一个固件。此时 grub-install 会输出 source_dir does not exist. Please specify --target or --directory
  • 如果在运行 grub-install 以后,被告知你的分区不是一个 EFI 分区,那这个分区很可能不是 Fat32

在固件启动管理器中创建一个GRUB条目

Tango-view-fullscreen.pngThis article or section needs expansion.Tango-view-fullscreen.png

Reason: 提供一个 efibootmgr 命令。 (Discuss in Talk:GRUB (简体中文))

grub-install会自动尝试在启动管理器中创建一个菜单项。如果没有,请参见UEFI#efibootmgr,了解使用efibootmgr来创建菜单项的说明。问题也可能在于你没有以UEFI模式启动CD/USB,参见UEFI#Create UEFI bootable USB from ISO

启动时进入了救急控制台

如果 GRUB 直接就启动到了救急控制台下,而且没报错,这可能是因为如下两种原因:

  • 可能是因为 grub.cfg 丢失或者位置不对。如果 GRUB UEFI 安装时设定了 --boot-directory 参数,而 grub.cfg 文件却不在那里,就会发生这样的问题。
  • 如果启动分区的分区号发生了变化(这个分区号会被直接编码到 grubx64.efi 文件中),也会出现这个问题。

GRUB UEFI 无法载入

下面是一个正常的 UEFI 的示例:

# efibootmgr -v
BootCurrent: 0000
Timeout: 3 seconds
BootOrder: 0000,0001,0002
Boot0000* GRUB HD(1,800,32000,23532fbb-1bfa-4e46-851a-b494bfe9478c)File(\EFI\GRUB\grubx64.efi)
Boot0001* Shell HD(1,800,32000,23532fbb-1bfa-4e46-851a-b494bfe9478c)File(\shellx64.efi)
Boot0002* Festplatte BIOS(2,0,00)P0: SAMSUNG HD204UI

如果启动后,屏幕直接变黑,几秒后就跳到了下一个启动项,根据相关链接的说法是,将 GRUB 移动到 root 分区上可能会解决这个问题。必须先删除启动项,然后在移动 GRUB 后重建。操作之后上述命令的输出中,GRUB 条目应该像这样:

Boot0000* GRUB HD(1,800,32000,23532fbb-1bfa-4e46-851a-b494bfe9478c)File(\grubx64.efi)

缺省/后备启动路径

一些 UEFI 固件在显示 UEFI NVRAM 启动条目之前,需要在一个已知的位置上有一个可启动文件。如果是这种情况, grub-install 会说明 efibootmgr 添加了一个启动 GRUB 的条目,但这个条目不会在 VisualBIOS 启动顺序选择器中显示。解决方法是把 GRUB 安装到缺省/后备启动路径当中:

# grub-install --target=x86_64-efi --efi-directory=esp --removable

或者你可以把已经安装好的 GRUB EFI 执行文件移动到缺省/后备路径中:

# mv esp/EFI/grub esp/EFI/BOOT
# mv esp/EFI/BOOT/grubx64.efi esp/EFI/BOOT/BOOTX64.EFI

"Invalid signature"(无效签名错误)

如果在启动 Windows 时出现了 "invalid signature" 错误(比如在重新分区或者添加了新硬盘后),删除 GRUB 的设备配置,然后让它重建一个:

# mv /boot/grub/device.map /boot/grub/device.map-old
# grub-mkconfig -o /boot/grub/grub.cfg

grub-mkconfig 此时就应该生成了新的启动项了,包括 Windows。确认能启动成功后,再将备份文件 /boot/grub/device.map-old 删除。

引导过程卡死

如果在 GRUB 载入内核并初始化 ramdisk 后引导过程卡死了,又没有错误信息的话,请尝试移除 add_efi_memmap 这个内核参数。

其他系统不能自动发现 Arch Linux

有人发现有些发行版不能使用 os-prober 自动发现 Arch Linux。据说如果 /etc/lsb-release 文件存在的话,可以提高探测能力。这个文件和和更新工具可以在 lsb-release 包中找到。

在 chroot 环境下安装时遇到警告

当位于 chroot 环境里,要在 LVM 系统上安装 GRUB 的时候(比如在安装系统的时候),你可能会收到一个这样的警告:

/run/lvm/lvmetad.socket: connect failed: No such file or directory

或者

WARNING: failed to connect to lvmetad: No such file or directory. Falling back to internal scanning.

这是因为在 chroot 环境里面 /run 是不可用的。只要每个步骤都做对了,这些警告不会影响系统启动,你可以放心继续进行下一步的系统安装。

GRUB 载入非常慢

当磁盘空间很小的时候 GRUB 的载入时间可能会很长。如果你遇到了这样的问题,检查一下你的 /boot 或者 / 分区是不是有足够的剩余空间。

error: unknown filesystem(未知文件系统错误)

因某些原因,GRUB 可能会不能启动并输出 error: unknown filesystem。如果你确定所有的 UUID 都对了而且所有的文件系统都是有效而且被 GRUB 支持的,问题的原因可能是你的 BIOS 启动分区不在驱动器的前 2 TB 空间里 [2]。 选择一个分区工具调整这个分区,让它完全在前 2 TB 空间中,然后重新安装和配置 GRUB。

这个错误也可能是因为一个 ext4 文件系统拥有 large_dir 特性,或者设置了 metadata_csum_seed

警告: 当你在/boot中启用文件系统特性时,请确保grub支持你的 文件系统 特性。

grub-reboot 不能重新设定

GRUB 好像不能写入 BTRFS 格式的根分区[3]。如果你使用 grub-reboot 来启动到另一个启动条目,就会没法更新其 on-disk 环境。要么换一个启动条目来运行 grub-reboot(例如在不同发行版之间切换的时候),要么考虑换个文件系统。你可以通过运行 grub-editenv create 来重设一个 "sticky" 条目,然后在 /etc/default/grub 中设置 GRUB_DEFAULT=0(不要忘了运行 grub-mkconfig -o /boot/grub/grub.cfg)。

不能在旧的 BTRFS 上进行安装

如果一个驱动器在没有创建分区表的情形下被格式化成 BTRFS(比如 /dev/sdx),之后又创建了一个分区表,那么会有部分 BTRFS 格式保留下来。大部分功能和操作系统都不会注意这个,但是 GRUB 则无法安装,即使使用 --force 参数也不行。

# grub-install: warning: Attempting to install GRUB to a disk with multiple partition labels. This is not supported yet..
# grub-install: error: filesystem `btrfs' does not support blocklists.

你可以把整个驱动器置零来解决问题,但还有一个办法既简单又能保留你的数据,那就是用 wipefs -o 0x10040 /dev/sdx 命令来擦掉 BTRFS superblock。

未找到 Windows 8/10

Windows 8/10 如果启用了 "Hiberboot", "Hybrid Boot" 或 "Fast Boot",可能会导致 Windows 分区无法被挂载。所以 grub-mkconfig 无法找到安装的 Windows。在 Windows 里禁用 Hiberboot,然后它就可以被添加到 GRUB 菜单了。

VirtualBox EFI 模式

对于Virtual Box 6.1及之前的版本,将 GRUB 安装到缺省/后备启动路径

也可参考 VirtualBox (简体中文)#以 EFI 模式安装

Device /dev/xxx not initialized in udev database even after waiting 10000000 microseconds

如果 grub-mkconfig 卡住然后显示如下错误信息:

WARNING: Device /dev/xxx not initialized in udev database even after waiting 10000000 microseconds

你需要使用下列命令为 chroot 环境提供 /run/lvm/ 访问支持:

# mkdir /mnt/hostlvm
# mount --bind /run/lvm /mnt/hostlvm
# arch-chroot /mnt
# ln -s /hostlvm /run/lvm

参见 FS#61040workaround

GRUB 救急与加密启动

在使用加密启动,而你没法键入正确的密码的时候,就会进入 GRUB 救急命令行。

这个救急命令行只有有限的功能,可以使用下面的命令来完成启动:

grub rescue> cryptomount <分区>
grub rescue> insmod normal
grub rescue> normal

更好的介绍参见 这个帖子

参阅