GRUB
GRUB (GRand Unified Bootloader) 是一个引导加载程序。当前的 GRUB 也被称为 GRUB 2。原始 GRUB,或称 GRUB Legacy,对应于版本 0.9x。本文档仅描述 GRUB 2。
esp 表示 EFI 系统分区(也称为 ESP)的挂载点。支持的文件系统
GRUB 内置了对多种文件系统的支持,特别是 FAT32、ext4、Btrfs 或 XFS。有关一些注意事项,请参阅#不支持的文件系统。
UEFI 系统
- 建议阅读并理解 统一可扩展固件接口、分区#GUID 分区表 和 Arch 引导过程#UEFI 2 页面。
- 安装以使用 UEFI 时,重要的是以 UEFI 模式引导安装介质,否则 efibootmgr 将无法添加 GRUB UEFI 引导条目。安装到回退引导路径即使在 BIOS 模式下也能正常工作,因为它不会触及 NVRAM。
- 要从使用 UEFI 的磁盘引导,需要一个 EFI 系统分区。请遵循 EFI 系统分区#检查现有分区 来了解您是否已有一个,否则您需要创建一个。
- 整个文章假设通过
insmod插入额外的 GRUB2 模块是可能的。如#Shim-lock中所述,在启用安全启动的 UEFI 系统上,情况并非如此。如果您想在安全启动系统上使用任何未包含在标准 GRUB EFI 文件grubx64.efi中的额外 GRUB 模块,您必须使用grub-mkstandalone重新生成 GRUB EFIgrubx64.efi,或使用grub-install重新安装 GRUB 并包含额外的 GRUB 模块。
安装
- UEFI 固件在不同制造商之间的实现方式不尽相同。下面描述的程序旨在适用于各种 UEFI 系统,但对于尽管应用了此方法仍遇到问题的用户,建议分享有关其硬件特定情况的详细信息,以及可能的解决方案。已提供 /EFI 示例文章以供参考。
- 本节假设您正在为 x64(64 位)UEFI 安装 GRUB。对于 IA32(32 位)UEFI(不要与 32 位 CPU 混淆),请在适当的地方将
x86_64-efi替换为i386-efi。请遵循 统一可扩展固件接口#检查固件位数 中的说明来确定您的 UEFI 位数。
首先,安装软件包 grub 和 efibootmgr:GRUB 是引导加载程序,而 efibootmgr 由 GRUB 安装脚本用于将引导条目写入 NVRAM。
然后按照以下步骤将 GRUB 安装到您的磁盘
- 挂载 EFI 系统分区,并在本节的其余部分,用其挂载点替换
esp。 - 选择一个引导加载程序标识符,此处命名为
GRUB。将在esp/EFI/中创建一个同名目录来存储 EFI 二进制文件,并且这个名称将在 UEFI 引导菜单中用于标识 GRUB 引导条目。 - 执行以下命令将 GRUB EFI 应用程序
grubx64.efi安装到esp/EFI/GRUB/,并将其模块安装到/boot/grub/x86_64-efi/。
- 注
- 确保在要将 GRUB 安装为引导加载程序的系统内部安装软件包并运行
grub-install命令。也就是说,如果您正在从 Live 安装环境引导,则在运行grub-install时需要位于 chroot 环境内。如果出于某种原因需要从已安装系统外部运行grub-install,请在--boot-directory=选项中附加挂载的/boot目录的路径,例如--boot-directory=/mnt/boot。 - 一些主板无法处理包含空格的
bootloader-id。 - 仅支持 EFI 上的 RAID mdadm 1 版本 / 元数据 0.90 或 1.0!因此,分区以 FAT 文件系统的完整副本开始,然后在末尾带有 mdadm 标签。
grub-install需要--no-nvram,否则会报错efibootmgr: option requires an argument -- 'd'。这是一个长期存在的 bug(Ubuntu 讨论)。最快的解决方法是使用 efibootmgr 手动为数组中的每个分区添加条目(Gentoo wiki 对 efibootmgr 的使用进行了更深入的介绍)。
- 确保在要将 GRUB 安装为引导加载程序的系统内部安装软件包并运行
# grub-install --target=x86_64-efi --efi-directory=esp --bootloader-id=GRUB
上述安装完成后,主要的 GRUB 目录位于 /boot/grub/。请参阅 /Tips and tricks#替代安装方法 以了解如何指定备用位置。请注意,grub-install 也会尝试在固件引导管理器中创建条目,在上例中命名为 GRUB - 但如果您的引导条目已满或系统阻止引导顺序被修改(例如 Thinkpad BIOS 中有一个名为 "Boot Order Lock" 的设置,需要禁用才能使 efibootmgr 添加/删除条目),则此操作将失败;请使用 efibootmgr 删除不必要的条目。
--removable 选项,GRUB 将安装到 esp/EFI/BOOT/BOOTX64.EFI (或 i386-efi 目标下的 esp/EFI/BOOT/BOOTIA32.EFI),并且您将能够从驱动器启动,即使 EFI 变量被重置或您将驱动器移动到另一台计算机。通常,您可以通过选择驱动器本身来执行此操作,类似于使用 BIOS 的方式。如果与 Windows 双重引导,请注意 Windows 通常会在此处放置一个 EFI 可执行文件,但其唯一目的是重新创建 Windows 的 UEFI 启动条目。如果您在 Mac 上安装 GRUB,则必须使用此选项。某些台式机主板只会在此位置查找 EFI 可执行文件,这使得此选项成为必需的,尤其是在 MSI 主板上。如果您执行 UEFI 更新,此更新可能会删除现有的 UEFI 启动条目。因此,启用“可移动”启动条目是一种潜在的备用策略。--efi-directory和--bootloader-id特定于 GRUB UEFI,--efi-directory取代了已弃用的--root-directory。- 您可能会注意到
grub-install命令中缺少 device_path 选项(例如:/dev/sda)。实际上,GRUB UEFI 安装脚本会忽略任何提供的 device_path。确实,UEFI 引导加载程序根本不使用 MBR 引导代码或分区引导扇区。
如果遇到问题,请参阅UEFI 故障排除。此外,请参阅 /Tips and tricks#UEFI 进一步阅读。
安全启动支持
GRUB 完全支持安全启动,可以使用 CA 密钥或 shim;但是,安装命令取决于您打算使用哪种方法。
CA 密钥
要使用 CA 密钥,命令是
# grub-install --target=x86_64-efi --efi-directory=esp --bootloader-id=GRUB --modules="tpm" --disable-shim-lock
Shim-lock
使用 Shim-lock 时,GRUB 只有在其 EFI 二进制文件包含所有必要的模块以读取包含 vmlinuz 和 initramfs 镜像的文件的支持时,才能在安全启动模式下成功引导。
自 GRUB 版本 2.06.r261.g2f4430cc0 起,在安全启动模式下通过 insmod 加载模块已不再允许,因为这会违反不侧载任意代码的预期。如果 GRUB 模块未嵌入 EFI 二进制文件中,并且 GRUB 尝试侧载/insmod 它们,GRUB 将会引导失败并显示消息
error: prohibited by secure boot policy
根据其官方构建脚本,Ubuntu 将以下 GRUB 模块嵌入到其签名的 GRUB EFI 二进制文件 grubx64.efi 中
- “基本”模块,用于从 CD 或简单分区磁盘启动:
all_video,boot,btrfs,cat,chain,configfile,echo,efifwsetup,efinet,ext2,fat,font,gettext,gfxmenu,gfxterm,gfxterm_background,gzio,halt,help,hfsplus,iso9660,jpeg,keystatus,loadenv,loopback,linux,ls,lsefi,lsefimmap,lsefisystab,lssal,memdisk,minicmd,normal,ntfs,part_apple,part_msdos,part_gpt,password_pbkdf2,png,probe,reboot,regexp,search,search_fs_uuid,search_fs_file,search_label,sleep,smbios,squash4,test,true,video,xfs,zfs,zfscrypt,zfsinfo - "平台特定"模块,例如用于 x86_64-efi 架构
play:在引导时播放声音cpuid:在引导时获取 CPU 信息tpm:支持测量引导 / 可信平台模块
- "高级"模块,包括模块
您必须将 GRUB 模块列表构建为一个 shell 变量,我们将其命名为 GRUB_MODULES。您可以将最新的 Ubuntu 脚本作为起点,并删除系统中不需要的模块。省略模块将使引导过程相对更快,并节省 ESP 分区上的空间。
您还需要一个 安全启动高级目标 (SBAT) 文件/部分包含在 EFI 二进制文件中,以提高安全性;如果 GRUB 是从 UEFI shim 引导加载程序启动的。此 SBAT 文件/部分包含有关 GRUB 二进制文件(版本、维护者、开发者、上游 URL)的元数据,并使 shim 更容易阻止加载存在安全漏洞的某些 GRUB 版本[1][2],如 shim 的 UEFI shim 引导加载程序安全启动生命周期改进文档中所述。
第一个阶段的 UEFI 引导加载程序 shim 如果缺少 grubx64.efi 中的 SBAT 部分,将无法启动 grubx64.efi!
如果 GRUB 已安装,则一个示例 SBAT .csv 文件位于 /usr/share/grub/sbat.csv。
使用提供的 /usr/share/grub/sbat.csv 文件和所有必需的 GRUB_MODULES 重新安装 GRUB 并对其进行签名
# grub-install --target=x86_64-efi --efi-directory=esp --modules=${GRUB_MODULES} --sbat /usr/share/grub/sbat.csv
# sbsign --key MOK.key --cert MOK.crt --output esp/EFI/GRUB/grubx64.efi esp/EFI/GRUB/grubx64.efi
# cp esp/EFI/GRUB/grubx64.efi esp/EFI/BOOT/grubx64.efi
重启,在 MokManager 中选择密钥,安全启动应该就可以正常工作了。
使用安全启动
安装完成后,请参阅 安全启动#实施安全启动 以获取有关启用它的说明。
如果您使用 CA Keys 方法,则可以使用 sbctl 自动化密钥管理、注册和文件签名,有关详细信息,请参阅 安全启动#使用 sbctl 辅助过程。
BIOS 系统
GUID 分区表 (GPT) 特定说明
在 BIOS/GPT 配置中,需要一个 BIOS 引导分区。GRUB 将其 core.img 嵌入到此分区中。
- 在尝试此方法之前,请记住并非所有系统都支持此分区方案。请阅读 分区#GUID 分区表 以了解更多信息。
- BIOS 引导分区仅在 BIOS/GPT 设置中由 GRUB 使用。在 BIOS/MBR 设置中,GRUB 使用 post-MBR 间隙来嵌入
core.img。然而,在 GPT 中,不能保证第一个分区之前有未使用的空间。 - 对于 UEFI 系统,不需要此额外分区,因为在这种情况下不会嵌入引导扇区。但是,UEFI 系统仍然需要一个 EFI 系统分区。
在磁盘上创建一个 MiB 分区(使用 fdisk 或 gdisk 时为 +1M),该分区没有文件系统,并且分区类型 GUID 为 21686148-6449-6E6F-744E-656564454649。
- fdisk: 创建一个分区并使用
t命令将分区类型更改为BIOS boot。 - gdisk: 创建一个分区类型为
ef02的分区。 - GNU Parted: 创建一个分区并设置
bios_grub标志。
此分区可以按任何顺序排列,但必须位于磁盘的前 2 TiB 内。此分区必须在 GRUB 安装之前创建。分区准备就绪后,按照下面的说明安装引导加载程序。
第一个分区之前的空间也可以用作 BIOS 引导分区,尽管它将不符合 GPT 对齐规范。由于该分区不会被常规访问,性能问题可以忽略,但某些磁盘实用程序会显示有关它的警告。在 fdisk 或 gdisk 中,创建一个从扇区 34 开始到 2047 结束的新分区,并设置类型。为了使可见分区从基础开始,请考虑将此分区放在最后。
主引导记录 (MBR) 特定说明
在许多 MBR 分区的系统中,post-MBR 间隙(在 512 字节 MBR 区域之后,以及在第一个分区开始之前)通常为 31 KiB,前提是分区表满足 DOS 兼容性柱面对齐问题。然而,建议使用大约 1 到 2 MiB 的 post-MBR 间隙,以提供足够的空间来嵌入 GRUB 的 core.img(FS#24103)。建议使用支持 1 MiB 分区对齐的分区工具来获取此空间,并满足其他非 512 字节扇区问题(这些问题与 core.img 的嵌入无关)。
安装
安装 grub 软件包。(如果已安装 grub-legacyAUR,它将替换它。)然后执行
# grub-install --target=i386-pc /dev/sdX
其中 i386-pc 是故意使用的,无论您的实际架构如何,而 /dev/sdX 是要将 GRUB 安装到的**磁盘**(**不是分区**)。例如 /dev/sda 或 /dev/nvme0n1,或 /dev/mmcblk0。有关块设备命名方案的描述,请参阅 设备文件#块设备名称。
现在您必须生成主配置文件。
如果您使用 LVM 作为您的 /boot,您可以在多个物理磁盘上安装 GRUB。
请参阅 grub-install(8) 和 GRUB 手册 以获取有关 grub-install 命令的更多详细信息。
配置
在已安装的系统上,GRUB 在每次启动时都会加载 /boot/grub/grub.cfg 配置文件。您可以按照#生成的 grub.cfg 来使用一个工具,或按照#自定义 grub.cfg 来手动创建。
生成的 grub.cfg
本节仅涵盖编辑 /etc/default/grub 配置文件。有关更多信息,请参阅 /Tips and tricks。
生成主配置文件
安装后,需要生成主配置文件 /boot/grub/grub.cfg。生成过程可以受到 /etc/default/grub 中的各种选项以及 /etc/grub.d/ 中的脚本的影响。有关 /etc/default/grub 中选项的列表以及每个选项的简要说明,请参阅 GNU 的文档。
如果您没有进行额外的配置,自动生成将确定用于引导配置文件的系统根文件系统。为此成功,重要的是系统必须已引导或已chrooted。
- 默认文件路径是
/boot/grub/grub.cfg,而不是/boot/grub/i386-pc/grub.cfg。 - 如果您尝试在 chroot 或 systemd-nspawn 容器中运行 grub-mkconfig,您可能会发现它无法工作:
grub-probe: error: failed to get canonical path of /dev/sdaX。在这种情况下,请尝试使用 arch-chroot,如BBS 帖子中所述。
使用 grub-mkconfig 工具生成 /boot/grub/grub.cfg
# grub-mkconfig -o /boot/grub/grub.cfg
默认情况下,生成脚本会自动为所有已安装的 Arch Linux 内核在生成的配置文件中添加菜单项。
- 安装或删除 内核后,您只需要重新运行上述 grub-mkconfig 命令。
- 有关管理多个 GRUB 条目的提示,例如同时使用 linux 和 linux-lts 内核时,请参阅 /Tips and tricks#多个条目。
要自动添加其他已安装操作系统的条目,请参阅#检测其他操作系统。
您可以通过编辑 /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 语句。
/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
然后重试。
- 确切的挂载点无关紧要,os-prober 会读取
mtab来识别搜索可引导条目的位置。 - 请记住,每次运行 grub-mkconfig 时都要挂载分区,以便每次都包含其他操作系统。
- 在 chroot 中运行时,os-prober 可能无法正常工作。如果遇到此问题,请在重启进入系统后再试。
Windows
对于以 UEFI 模式安装的 Windows,请确保包含 Windows Boot Manager (bootmgfw.efi) 的 EFI 系统分区已挂载。以 root 身份运行 os-prober 来检测并生成其条目。
对于以 BIOS 模式安装的 Windows,请挂载 Windows 系统分区(其 文件系统标签应为 System Reserved 或 SYSTEM)。以 root 身份运行 os-prober 来检测并生成其条目。
附加参数
要将自定义的附加参数传递给 Linux 镜像,可以在 /etc/default/grub 中设置 GRUB_CMDLINE_LINUX + GRUB_CMDLINE_LINUX_DEFAULT 变量。这两个变量会被连接起来,在生成常规启动条目时传递给内核。对于恢复启动条目,仅使用 GRUB_CMDLINE_LINUX 进行生成。
不必同时使用两者,但可能会有用。例如,您可以使用 GRUB_CMDLINE_LINUX_DEFAULT="resume=UUID=swap-partition-uuid quiet",其中 swap-partition-uuid 是您的交换分区 UUID,以启用 休眠后的恢复。这将生成一个没有 resume 和没有 quiet(抑制从该菜单条目启动时的内核消息)的恢复启动条目。不过,其他(常规)菜单条目将具有它们作为选项。
默认情况下,grub-mkconfig 会确定根文件系统的 UUID 以用于配置。要禁用此功能,请取消注释 GRUB_DISABLE_LINUX_UUID=true。
要生成 GRUB 恢复条目,您必须确保 GRUB_DISABLE_RECOVERY 在 /etc/default/grub 中未设置为 true。
有关更多信息,请参阅 Kernel parameters。
设置顶层菜单项
默认情况下,grub-mkconfig 使用 sort -V 对包含的内核进行排序,并将该列表中的第一个内核作为顶层条目。这意味着,例如,由于 /boot/vmlinuz-linux-lts 在 /boot/vmlinuz-linux 之前排序,如果您同时安装了 linux-lts 和 linux,LTS 内核将是顶层菜单项,这可能不是您想要的。可以通过在 /etc/default/grub 中指定 GRUB_TOP_LEVEL="kernel-path" 来覆盖此行为。例如,要使常规内核成为顶层菜单项,可以使用 GRUB_TOP_LEVEL="/boot/vmlinuz-linux"。
LVM
如果您的 /boot 或 / 根分区使用 LVM,请确保 lvm 模块已预加载。
/etc/default/grub
GRUB_PRELOAD_MODULES="... lvm"
RAID
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)
要在使用 RAID1 作为 /boot 分区(或使用 /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 上。
加密的 /boot
GRUB 还支持启动加密的 /boot。这是通过解锁一个 LUKS 块设备来实现的,以便读取其配置并从中加载任何 initramfs 和 kernel。此选项试图解决拥有一个未加密的 boot 分区的问题。
/boot *不*需要放在单独的分区中;它也可以保留在系统的根 / 目录树下。要启用此功能,请像往常一样使用 LUKS 加密包含 /boot 的分区。然后在 /etc/default/grub 中添加以下选项
/etc/default/grub
GRUB_ENABLE_CRYPTODISK=y
此选项由 grub-install 用于生成 grub core.img。
修改此选项或加密分区后,请确保安装 grub。
在不进行进一步更改的情况下,系统会提示您两次输入密码:第一次是为了让 GRUB 在早期启动时解锁 /boot 挂载点,第二次是为了解锁根文件系统本身,这是由 initramfs 实现的。您可以使用 密钥文件来避免这种情况。
- 如果您使用特殊的键盘映射,默认的 GRUB 安装将不知道它。这与如何输入密码以解锁 LUKS 块设备相关。请参阅 /Tips and tricks#Manual configuration of core image for early boot。
- 如果您遇到密码提示显示问题(有关 cryptouuid、cryptodisk 或“设备未找到”的错误),请尝试重新安装 GRUB 并将
--modules="part_gpt part_msdos"追加到grub-install命令的末尾。
/boot。LUKS2
使用 #Installation 部分所述的 grub-install 创建一个支持 LUKS 的可引导 GRUB 镜像。请注意以下注意事项:
- GRUB 2.06 加入了对 LUKS2 的初步支持,但存在一些限制,在 GRUB 2.12rc1 中仅部分得到解决。请参阅 GRUB bug #55093。
- 自 GRUB 2.12rc1 起,
grub-install可以创建一个核心镜像来解锁 LUKS2。然而,它仅支持 PBKDF2,不支持 Argon2。 - 不支持 Argon2id(cryptsetup 默认)和 Argon2i PBKDF(GRUB bug #59409),只支持 PBKDF2。
- 提示 您可以使用 grub-improved-luks2-gitAUR,该包已针对 LUKS2 和 Argon2 支持进行了修补。请注意,该软件包的 Argon2 支持需要 UEFI 系统。[3]
grub-mkimage 和自定义 GRUB 配置文件手动创建一个 EFI 二进制文件。例如,/boot/grub/grub-pre.cfg,其中包含对 cryptomount、insmod normal 和 normal 的调用。这不再需要,grub-install 就足够了。但是,您可能需要在从 2.06 升级后至少运行一次 grub-mkconfig -o /boot/grub/grub.cfg。如果您在启动时输入了无效的密码并最终进入 GRUB 救援 shell,请尝试 cryptomount -a 来挂载所有(希望只有一个)加密分区,或使用 cryptomount -u $crypto_uuid 来挂载特定的分区。然后像往常一样继续使用 insmod normal 和 normal。
如果您输入了正确的密码,但立即返回“无效密码”错误,请确保指定了正确的加密模块。使用 cryptsetup luksDump /dev/nvme0n1p2 查看哈希函数(SHA-256、SHA-512)是否与安装的模块(gcry_sha256、gcry_sha512)匹配,并且 PBKDF 算法是 pbkdf2。可以使用 cryptsetup luksConvertKey --hash sha256 --pbkdf pbkdf2 /dev/nvme0n1p2 为现有密钥更改哈希和 PBKDF 算法。在正常情况下,处理密码应该需要几秒钟。
自定义 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)设置启动分区,其中存储着内核和 GRUB 模块(boot 不需要是单独的分区,也可以只是“根”分区(/)下的一个目录)。
LoaderDevicePartUUID
为了让 GRUB 设置 systemd-gpt-auto-generator(8) 用于 GPT 分区自动挂载所需的 LoaderDevicePartUUID UEFI 变量,请在 grub.cfg 中加载 bli 模块。
if [ "$grub_platform" = "efi" ]; then insmod bli fi
启动菜单示例
/boot/grub/grub.cfg 时,也可以使用这些启动条目。将它们添加到 /etc/grub.d/40_custom 并重新生成主配置文件,或将它们添加到 /boot/grub/custom.cfg。有关管理多个 GRUB 条目的提示,例如同时使用 linux 和 linux-lts 内核时,请参阅 /Tips and tricks#多个条目。
有关 Archiso 和 Archboot 启动菜单条目,请参阅 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 可以链式加载其他 EFI 二进制文件。
if 语句中:if [ ${grub_platform} == "efi" ]; then
place UEFI-only menu entries here
fiUEFI 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 应用程序并将 gdisk_x64.efi 复制到 esp/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
}
链式加载统一内核镜像
如果您有一个通过 Secure Boot 或其他方式生成的统一内核镜像,您可以将其添加到启动菜单。例如:
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/initramfs.img (if the other kernel uses/needs one)
}
或者让 GRUB 按 UUID 或文件系统标签搜索正确的分区。
menuentry "Other Linux" {
# assuming that UUID is 763A-9CB6
search --no-floppy --set=root --fs-uuid 763A-9CB6
# search by label OTHER_LINUX (make sure that partition label is unambiguous)
#search --no-floppy --set=root --label OTHER_LINUX
linux /boot/vmlinuz (add other options here as required, for example: root=UUID=763A-9CB6)
initrd /boot/initramfs.img (if the other kernel uses/needs one)
}
如果其他发行版已经有一个有效的 /boot 文件夹,其中安装了 GRUB、grub.cfg、内核和 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 系统分区并从中运行引导加载程序。
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
或者,您可以运行 lsblk --fs 并从中读取 EFI 系统分区的 UUID。
$hints_string 命令将确定 EFI 系统分区的 /dev/sda4 上的位置,在此示例中为硬盘 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 的存在,Windows EFI 文件路径的大小写可能存在差异。
在 BIOS/MBR 模式下安装的 Windows
bootmgr,并且在 BIOS/MBR 设置中启动 Windows 时不再需要链式加载分区引导扇区。/bootmgr 位于*系统分区*上,而不是您的“真实”Windows 分区(通常是 C:)。系统分区的文件系统标签是 System Reserved 或 SYSTEM,分区大小约为 100 到 549 MiB。有关更多信息,请参阅 Wikipedia:System partition and boot partition。在本节中,我们假设您的 Windows 分区是 /dev/sda1。不同的分区将改变 hd0,msdos1 的每个实例。
在两个示例中,XXXX-XXXX 都是文件系统 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 XXXX-XXXX
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 XXXX-XXXX
ntldr /ntldr
}
fi
\boot\bcd 错误(错误代码 0xc000000f)。您可以通过进入 Windows 恢复控制台(从安装盘启动 cmd.exe)并执行以下命令来修复:X:\> bootrec.exe /fixboot X:\> bootrec.exe /RebuildBcd
不要使用 bootrec.exe /Fixmbr,因为它会擦除 GRUB。或者,您可以使用故障排除菜单中的“启动修复”功能 - 它不会擦除 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
}
使用命令 shell
由于 MBR 太小,无法存储所有 GRUB 模块,因此只有菜单和一些基本命令驻留在其中。GRUB 的大部分功能保留在 /boot/grub/ 中的模块中,这些模块按需插入。在错误条件下(例如,如果分区布局发生更改),GRUB 可能会启动失败。发生这种情况时,可能会出现命令 shell。
GRUB 提供多个 shell/提示符。如果菜单读取存在问题,但引导加载程序能够找到磁盘,您很可能会进入“normal”shell。
grub>
如果存在更严重的问题(例如,GRUB 找不到必需的文件),您可能会进入“rescue”shell。
grub rescue>
rescue shell 是 normal shell 的一个受限子集,功能少得多。如果进入 rescue shell,首先尝试插入“normal”模块,然后启动“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 命令)。这仅在 normal shell 模式下有效,在 rescue 模式下无效。要启用分页器,请在 GRUB 命令 shell 中输入:
sh:grub> set pager=1
使用命令 shell 环境启动操作系统
grub>
GRUB 的命令 shell 环境可用于启动操作系统。常见场景可能是通过*链式加载*启动存储在驱动器/分区上的 Windows / Linux。
链式加载意味着从当前加载器加载另一个引导加载程序,即链式加载。
另一个引导加载程序可能嵌入在分区磁盘(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。
链式加载磁盘 MBR 或无分区磁盘 VBR
set root=hdX chainloader +1 boot
链式加载 UEFI 模式下安装的 Windows/Linux
insmod fat set root=(hd0,gpt4) chainloader /EFI/Microsoft/Boot/bootmgfw.efi boot
insmod fat 用于加载 FAT 文件系统模块,以便在 UEFI 系统分区上访问 Windows 引导加载程序。在此示例中,(hd0,gpt4) 或 /dev/sda4 是 UEFI 系统分区。chainloader 行中的条目指定了要链式加载的 .efi 文件的路径。
正常加载
请参阅 #Using the rescue console 中的示例。
使用救援控制台
请先参阅 #Using the command shell。如果无法激活标准 shell,一种可能的解决方案是使用 live CD 或其他救援磁盘启动,以纠正配置错误并重新安装 GRUB。但是,这样的启动盘并非总是可用(也不是必需的);救援控制台非常健壮。
GRUB 救援中可用的命令包括 insmod、ls、set 和 unset。此示例使用 set 和 insmod。set 修改变量,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
这引入了 linux 和 initrd 命令,您应该很熟悉。
一个例子:启动 Arch Linux
set root=(hd0,5) linux /boot/vmlinuz-linux root=/dev/sda5 initrd /boot/initramfs-linux.img boot
对于单独的 boot 分区(例如,在使用 UEFI 时),请同样相应地更改行:
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。有关详细信息,请参阅 #Installation。
GRUB 移除
UEFI 系统
在移除 grub 之前,请确保已安装并配置了其他引导加载程序来接管。
$ efibootmgr
BootOrder: 0003,0001,0000,0002 Boot0000* Windows Boot Manager HD(2,GPT,4dabbedf-191b-4432-bc09-8bcbd1d7dabf,0x109000,0x32000)/File(\EFI\Microsoft\Boot\bootmgfw.efi) Boot0001* GRUB HD(2,GPT,4dabbedf-191b-4432-bc09-8bcbd1d7dabf,0x109000,0x32000)/File(\EFI\GRUB\grubx64.efi) Boot0002* Linux-Firmware-Updater HD(2,GPT,5dabbedf-191b-4432-bc09-8bcbd1d7dabf,0x109000,0x32000)/File(\EFI\arch\fwupdx64.efi) Boot0003* Linux Boot Manager HD(2,GPT,4dabbedf-191b-4432-bc09-8bcbd1d7dabf,0x109000,0x32000)/File(\EFI\systemd\systemd-bootx64.efi)
如果 BootOrder 中 grub 是第一个条目,请安装另一个引导加载程序将其置于其前面,例如 systemd-boot。然后可以使用其 bootnum 移除 grub。
# efibootmgr --delete-bootnum -b 1
同时删除 esp/EFI/grub 和 /boot/grub 目录。
BIOS 系统
要将 grub 替换为任何其他 BIOS 引导加载程序,只需安装它们,它们将覆盖MBR 引导代码。
grub-install 创建 /boot/grub 目录,该目录需要手动删除。不过,有些用户会想保留它,以备将来重新安装 grub。
迁移到 UEFI/GPT 后,您可能希望使用 dd 删除 MBR 引导代码。
故障排除
不支持的文件系统
如果 GRUB 不支持根文件系统,则必须创建一个具有受支持文件系统的替代 /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 从 2.0.4 版本开始支持 F2FS,但它无法正确读取 F2FS 分区上带有 extra_attr 标志创建的启动文件。
启用调试消息
将
set pager=1 set debug=all
到 grub.cfg。
msdos 风格的错误消息
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(块 63)之后开始,而没有通常的 1 MiB(2048 块)的间隔时,就会发生这种情况。请参阅#Master Boot Record (MBR) specific instructions。
UEFI
常见的安装错误
- 在某些 UEFI 设备上可能出现的错误是
Could not prepare Boot variable: Read-only file system。您必须使用读写模式重新挂载/sys/firmware/efi/efivars。# mount -o remount,rw,nosuid,nodev,noexec --types efivarfs efivarfs /sys/firmware/efi/efivars
请参阅Gentoo Wiki 关于安装引导加载程序。 - 如果您在运行 grub-install 时遇到 sysfs 或 procfs 的问题,并且它提示您必须运行
modprobe efivarfs,请尝试使用上述命令挂载 efivarfs。 - 没有
--target或--directory选项,grub-install 无法确定要安装哪个固件。在这种情况下,grub-install将打印source_dir does not exist. Please specify --target or --directory。 - 如果在运行 grub-install 后收到
error: esp doesn't look like an EFI partition,那么该分区很可能不是 FAT32 格式的。
在固件引导管理器中创建 GRUB 条目
grub-install 会自动尝试在引导管理器中创建一个菜单项。如果它没有这样做,请参阅 UEFI#efibootmgr 以获取使用 efibootmgr 创建菜单项的说明。然而,问题很可能是您没有以 UEFI 模式启动 CD/USB,如 Installation guide#Verify the boot mode 中所述。
作为创建 GRUB 条目在固件引导管理器中的另一个例子,可以考虑 efibootmgr -c。这假定 /dev/sda1 是 EFI 系统分区,并且挂载在 /boot/efi。这些是 efibootmgr 的默认行为。它创建了一个新的引导选项,称为“Linux”,并将其放在引导顺序列表的顶部。可以传递选项来修改默认行为。默认的 OS Loader 是 \EFI\arch\grub.efi。
进入救援 shell
如果 GRUB 加载但没有错误地进入救援 shell,可能是由于以下两个原因之一:
- 这可能是因为缺少或放错位置的
grub.cfg。如果 GRUB UEFI 是使用--boot-directory安装的,并且grub.cfg丢失,就会发生这种情况。 - 当引导分区(硬编码在
grubx64.efi文件中)发生更改时,也会发生这种情况。
GRUB UEFI 未加载
一个工作的 UEFI 示例:
# efibootmgr -u
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 移动到分区根目录可能有助于解决问题。必须删除并重新创建启动选项。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
无效签名
如果尝试启动 Windows 时出现“无效签名”错误,例如在重新配置分区或添加其他硬盘之后,请(重新)删除 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
有人报告说,其他发行版可能在自动查找 Arch Linux 时遇到 os-prober 的问题。如果出现此问题,据报告,通过存在 /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.
这是因为 /run 在 chroot 中不可用。这些警告不会阻止系统启动,前提是所有操作都已正确完成,因此您可以继续安装。
GRUB 加载缓慢
当磁盘空间不足时,GRUB 加载可能需要很长时间。当您遇到问题时,请检查您的 /boot 或 / 分区是否有足够的可用磁盘空间。
error: unknown filesystem
GRUB 可能会输出 error: unknown filesystem 并拒绝启动,原因有几种。如果您确定所有 UUID 都正确,并且所有文件系统都有效且受支持,可能是因为您的BIOS Boot Partition位于驱动器前 2 TiB 之外 [4]。使用您选择的分区工具确保该分区完全位于前 2 TiB 内,然后重新安装并重新配置 GRUB。
此错误也可能由具有不受支持功能的 ext4 文件系统引起:
large_dir- 不支持。metadata_csum_seed- 将在 GRUB 2.11 中支持(commit)。
/boot 文件系统上启用新的 文件系统 功能之前,请务必检查 GRUB 对这些功能的支持。grub-reboot 未重置
GRUB 似乎无法写入根 Btrfs 分区 [5]。因此,如果您使用 grub-reboot 启动到另一个条目,它将无法更新其磁盘上的环境。要么从另一个条目运行 grub-reboot(例如,在各种发行版之间切换时),要么考虑使用不同的文件系统。您可以通过执行 grub-editenv create 并设置 /etc/default/grub 中的 GRUB_DEFAULT=0 来重置一个“粘性”条目(不要忘记 grub-mkconfig -o /boot/grub/grub.cfg)。
旧 Btrfs 阻止安装
如果驱动器在未创建分区表(例如 /dev/sdx)的情况下使用 Btrfs 格式化,然后又写入了分区表,那么 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 超级块,同时保留您的数据。
找不到 Windows 8/10
Windows 8/10 中一项称为“Hiberboot”、“Hybrid Boot”或“Fast Boot”的设置会阻止 Windows 分区被挂载,因此 grub-mkconfig 找不到 Windows 安装。禁用 Windows 中的 Hiberboot 将允许将其添加到 GRUB 菜单。
GRUB 恢复模式和加密的 /boot
当使用 加密的 /boot 并且您未能输入正确的密码时,您将被置于 grub-rescue 提示符下。
此 grub-rescue 提示符的功能有限。请使用以下命令完成引导
grub rescue> cryptomount <partition> grub rescue> insmod normal grub rescue> normal
有关更详细的说明,请参阅 此博客文章。
GRUB 已安装但启动时未显示菜单
检查 /etc/default/grub 是否将 GRUB_TIMEOUT 设置为 0,如果是,请将其设置为一个正数:它设置在加载默认 GRUB 条目之前的秒数。同时检查 GRUB_TIMEOUT_STYLE 是否设置为 hidden,并将其设置为 menu,以便默认显示菜单。然后 重新生成主配置文件 并重新启动以检查是否有效。
如果无效,可能存在图形终端不兼容的问题。在 /etc/default/grub 中将 GRUB_TERMINAL_OUTPUT 设置为 console 以禁用 GRUB 图形终端。
GRUB 已安装,但在旧款联想机器上收到“错误代码 1962 - 未找到操作系统”消息
请参阅 通过伪装 EFI 启动条目修复联想的错误代码 1962。
每次 grub 更新时执行 grub-install/grub-mkconfig 的警告
您可以手动执行,或使用 pacman hook,例如
/etc/pacman.d/hooks/grub-update.hook
[Trigger] Operation = Upgrade Type = Package Target = grub [Action] Description = Regenerate grub if updated When = PostTransaction Depends = grub Exec = /bin/sh -c "/usr/bin/grub-install --efi-directory=esp --bootloader-id=GRUB && /usr/bin/grub-mkconfig -o /boot/grub/grub.cfg"
更改 grub-install 选项,例如 --efi-directory 路径,以匹配您的设置。