网上找到的一些示例说 update-grub 应该在 grub-install 之后运行。其他人则颠倒顺序。哪个是对的?
如果我有两个 Linux 安装(一个在 sda 上,一个在 sdb 上),如果我在 sda 安装上运行 update-grub,它将把 sda 安装放在启动菜单的顶部。如果我在 sdb 安装上运行 update-grub,它将把 sdb 安装放在菜单顶部。
假设 DEFAULT=0,理论上,这应该允许我通过在 BIOS 中选择引导设备来选择操作系统。 “grub-install /dev/sda”是否会更改 sda 引导菜单以对应于最后一个“update-grub”,无论它是从 Linux 的 sda 还是 sdb 版本运行?
答案1
update-grub
,至少在 Debian 及其类似版本(如 Ubuntu)中,基本上只是grub-mkconfig
.所以它创建/更新/重新生成 GRUB配置,而不是实际的引导加载程序本身。
其grub-install
实际作用取决于您运行的 GRUB 版本:传统 BIOS GRUB 还是 UEFI GRUB?
使用传统的 BIOS GRUB,grub-install
将(重新)写入主引导记录中嵌入的 GRUB 部分,并将物理磁盘块编号编码到其中,以便从其中读取 GRUB 的下一部分。它还将确定从哪个分区/boot/grub/grub.cfg
读取实际的 GRUB 配置文件 ( )。这里的一个重要因素是/boot/grub/device.map
文件,它告诉 GRUB BIOS(以及 GRUB)的设备编号如何映射到 Linux 磁盘设备。
对于 UEFI GRUB,GRUB 引导加载程序的主要部分将作为文件位于 EFI 系统分区中,通常为/boot/efi/EFI/<name of distribution>/grubx64.efi
或类似。此引导加载程序路径名存储在 UEFI 引导变量中的系统 NVRAM(= 存储 BIOS 设置的位置)中。 GRUB 的主要部分可能是完全独立的(如果使用安全引导,则必须是独立的!),或者它可以将附加功能作为 GRUB 模块加载,通常从/boot/grub
它所属的 Linux 发行版的目录中加载。
UEFI 引导变量将识别系统应使用的磁盘来查找 EFI 系统分区及其内部的引导加载程序文件。您可以使用命令自行查看这些变量efibootmgr -v
。该grub-install
命令将更新这些变量,除非您使用该--no-nvram
选项另行指定。
GRUB 运行后,接下来需要确定的是:它应该从哪里读取其配置文件?
grub-install
能够将 GRUBprefix
变量的所需值直接插入 GRUB 的主要部分。这嵌入前缀可以完全指定路径,也可以使用特定于体系结构的默认值在运行时保留某些部分来确定。
对于传统的 BIOS GRUB,嵌入的前缀通常会忽略实际的磁盘说明符,因此将使用加载 GRUB 的相同磁盘。在这种情况下,存储的前缀将是例如安装GRUB 的磁盘上的第一个主分区的(,msdos1)/grub
时间 。/boot
对于 UEFI GRUB,嵌入的前缀通常仅指定目录,然后它引用 EFI 系统分区 (ESP) 上的发行版目录。因此,典型的嵌入前缀是/EFI/debian
or/EFI/redhat
或类似的。磁盘和分区的默认值将是“加载 UEFI GRUB 二进制文件的同一分区”。
某些发行版(例如 RHEL)会将 UEFI GRUB 的实际配置直接放在 ESP 上。Debian 和相关发行版通常会再做一点间接操作:grub.cfg
ESP 上的 mini- 文件只包含几行,这些行将告诉 GRUB 从 Linux 启动并挂载所有磁盘后的文件读取实际配置文件/boot/grub/grub.cfg
。最简单的说,这个 mini-configuration 只有三行:
- 将 GRUB 根设置为指向包含真实 GRUB 配置文件(用于即将执行的
configfile
命令)的文件系统,在现代发行版中通常使用该search
命令和文件系统 UUID。该方案最古老的实现实际上可能使用了固定的 GRUB 分区规范,例如set root=(hd0,gpt1)
- 设置 GRUB
prefix
变量(如果安全启动未生效,则启用 GRUB 模块自动加载)。如果将加载配置的文件系统是 Linux 根文件系统,则此行将为set prefix=($root)'/boot/grub'
;如果/boot
是一个单独的文件系统,这一行将是set prefix=($root)'/grub'
configfile $prefix/grub.cfg
使用.读取实际的 GRUB 配置文件
如果包含 GRUB 配置的文件系统位于 LVM 逻辑卷、加密卷或软件 RAID 集上,则第一行将更加复杂,甚至可能根据需要添加其他行。
因此,对于传统 BIOS 和 UEFI,运行都grub-install
可以更新引导加载程序,以读取完全不同磁盘上完全不同的 GRUB 配置文件 - 尽管该过程的细节将完全不同。
efibootmgr
使用 UEFI,您实际上可以使用或来从操作系统内更改启动设备选择grub-install
。但这grub-install
是一个巨大的杀伤力:如果您的安装都是 UEFI 并且有自己独立的 ESP 分区,那么它们将有自己的 UEFI 启动变量,并且可以轻松地在它们之间进行选择efibootmgr
,或者实际上在 UEFI BIOS 设置中完成。
对于传统的 BIOS,情况有点混乱:您需要确保每个安装都/boot/grub/device.map
将该特定安装的磁盘标识为hd0
,而另一个安装的磁盘则标识为hd1
。然后用于grub-install
仅将引导加载程序写入每个安装自己的磁盘;永远不要到“相反”的磁盘。这样,即使另一个磁盘被完全删除,两个磁盘也将完全独立且可引导。如果需要,您可以在每个 GRUB 的配置文件中添加一个菜单项,该菜单项将允许您引导“相反”的安装。或者您可以直接使用 BIOS 选择启动磁盘。
您必须知道的是,传统 BIOS 的引导顺序选择器通常会选择用于引导 BIOS 功能的“第一”磁盘的磁盘,因此 GRUBhd0
将始终引用“当前在 BIOS 中选择用于引导的磁盘” ”。
/dev/sda
因此,如果您当前从(BIOS 表示为sda
)启动hd0
,并且希望该磁盘上的 GRUB 菜单项切换到 的/dev/sdb
启动菜单,则可以使用类似以下内容的命令:
menuentry "Switch to /dev/sdb"
{
# flip the disk mappings and reload configuration
drivemap -s (hd0) (hd1)
set root=<the identifier for sdb's partition that contains grub.cfg>
configfile /boot/grub/grub.cfg # or just /grub/grub.cfg is /boot is a separate partition
}
...同样在 /dev/sdb 的 GRUB 配置上也是如此。