GRUB 从 ISO 启动

作者:Kyle Rankin

去年我参与了一个项目,为电脑添加 OEM 风格的恢复分区。大多数 OEM 安装都带有一个自定义程序,只是将安装镜像覆盖到分区上,而在这个项目中,一切都基于开源软件。这个恢复分区只有几 GB 大小,足以容纳安装 DVD ISO 镜像和一些预配置 (preseed) 文件,以帮助自动化安装。如果用户想恢复到出厂安装的操作系统版本,他们可以从 GRUB 菜单中选择一个特殊选项,从 ISO 启动,并像使用 USB 密钥或 DVD 一样开始安装。

如果您阅读过一些关于如何从 GRUB 启动 ISO 的旧指南,您会发现有些情况下有相当复杂的说明,因为它们是为旧版本的 GRUB 编写的。幸运的是,对于最近版本的 GRUB2,从标准 ISO 启动并没有那么复杂。我在这里的示例基于最近的 Debian Stretch 安装 DVD,但相同的步骤应该适用于其他发行版和安装 ISO,只需进行一些调整。

创建分区

第一步是创建恢复分区。在我的例子中,我使用预配置脚本自动化了安装,但基本上我只是创建了一个足够大的分区来容纳安装 DVD。我确保给它一个标签,以便稍后将其与其他磁盘区分开来,并使其成为磁盘上的第二个分区。因为我通过自动化方式完成所有这些操作,所以我最终使用 dd 创建了当前正在使用的安装 DVD 的镜像,作为安装结束脚本,并将其转储到该分区根目录下一个名为 install_dvd1.iso 的文件中。当然,如果您从已经安装了操作系统的系统执行此操作,则可以直接将 ISO 复制到磁盘。

构建 GRUB 配置

下一步是构建一个 GRUB 配置,该配置将挂载 ISO 环回,并从该 ISO 中的内核和 initrd 文件启动。在基于 Debian 的系统上,您可以添加 bash 脚本,将额外的 GRUB 配置输出到 /etc/grub.d/,并运行 update-grub 来构建新的 grub.cfg 文件。但是,您也可以直接编辑 grub.cfg,或者使用您的发行版的 GRUB 配置脚本来添加以下菜单项。


set root='hd0,msdos2'
set isofile="/install_dvd1.iso"
menuentry "Install OS" {
 loopback loop (hd0,msdos2)$isofile
 linux (loop)/install.amd/vmlinuz vga=788 auto=true
  ↪file=/media/preseed.cfg -- quiet
 initrd (loop)/install.amd/initrd.gz
}
menuentry "Install OS (Expert)" {
 loopback loop (hd0,msdos2)$isofile
 linux (loop)/install.amd/vmlinuz vga=788 -- quiet
 initrd (loop)/install.amd/initrd.gz
}

让我们稍微分解一下这个 GRUB 配置。首先,您设置两个变量:GRUB 将使用的根分区(第一个磁盘上的第二个分区,GRUB 将其称为 hd0,msdos2)和 ISO 文件


set root='hd0,msdos2'
set isofile="/install_dvd1.iso"

接下来是两个独立的 GRUB 菜单(每个菜单都在 menuentry {} 节中)。第一个指向预配置 (preseed) 配置文件,并启动部分自动化的 Debian 安装,而另一个只是启动没有预配置文件的 Debian 安装程序,并充当“专家”模式,以便您可以手动选择每个安装选项。

到目前为止,GRUB 选项与其他 GRUB 配置非常相似,但这是发生变化的地方。


loopback loop (hd0,msdos2)$isofile

接下来,在每个菜单中,您定义一个 GRUB 将使用的环回设备


linux (loop)/install.amd/vmlinuz vga=788 auto=true
 ↪file=/media/preseed.cfg -- quiet
initrd (loop)/install.amd/initrd.gz

现在,无论何时您在配置中进一步引用 (loop),GRUB 都知道访问标记为 loop 的环回文件系统,该文件系统指向 (hd0,msdos2)/install_dvd1.iso。接下来的两行对于使用过 Linux GRUB 配置的人来说应该很熟悉,但有一个小小的变化

在第一行中,您定义要启动的内核以及要传递给它的选项,在下一行中,您将 GRUB 指向您希望它使用的 initrd 文件。但这里的主要区别在于,您在每个文件路径前都加上 (loop),以指示 GRUB 在该环回文件系统中查找文件。

一旦此配置进入 grub.cfg,您应该在下次启动时看到两个新的菜单选项。现在,当我第一次尝试以这种方式启动最新的 Debian 安装程序时,我遇到了一些问题。事实证明,ISO 本身附带的 initrd 不包含从硬盘驱动器上的 ISO 安装所需的安装程序脚本。它假设您只会从 DVD 或 USB 磁盘启动。因此,我发现我必须下载一个不同的 Debian 安装程序 initrd,并将其放在恢复磁盘上才能工作。我找到了一个可以工作的 initrd,here


set root='hd0,msdos2'
set isofile="/install_dvd1.iso"
menuentry "Install OS" {
 loopback loop (hd0,msdos2)$isofile
 linux (loop)/install.amd/vmlinuz vga=788 auto=true
  ↪file=/media/preseed.cfg -- quiet
 initrd /initrd.gz
}
menuentry "Install OS (Expert)" {
 loopback loop (hd0,msdos2)$isofile
 linux (loop)/install.amd/vmlinuz vga=788 -- quiet
 initrd /initrd.gz
}

当然,有了新的 initrd.gz 文件在我的恢复分区根目录下,我必须稍微更改我的 GRUB 配置以指向它

请注意,initrd 行现在指向 /initrd.gz。由于我已经在配置的早期定义了 root 变量,因此它知道在 hd0,msdos2 上查找该文件。一旦这个新的 initrd 就位,我就成功了,安装程序也按预期工作。如果您想将其用于不同的安装程序,只需确保内核启动后,它能够扫描磁盘以查找要使用的安装程序 ISO。

Kyle Rankin 是 Linux Journal 的技术编辑和专栏作家,也是 Purism 的首席安全官。他是 Linux Hardening in Hostile Networks, DevOps Troubleshooting, The Official Ubuntu Server Book, Knoppix Hacks, Knoppix Pocket Reference, Linux Multimedia HacksUbuntu Hacks 的作者,也是许多其他 O'Reilly 书籍的贡献者。Rankin 经常在安全和开源软件方面发表演讲,包括 BsidesLV、O'Reilly Security Conference、OSCON、SCALE、CactusCon、Linux World Expo 和 Penguicon。您可以在 @kylerankin 上关注他。