如何在UEFI机器上使用grub2从驱动器引导ISO文件?

我有一堆像GParted, CloneZilla, Boot-Repair, Ubuntu 14.04 32 bit这样的实时ISO文件,都下载在/opt目录下。在我的旧BIOS机器上,我只需要将它们添加到grub菜单中就可以启动它们。:-)

现在我有了一台UEFI机器,但是所有的信息都是针对BIOS机器的。

从grub启动这些ISO文件的步骤是什么?

每次都要把它们“刻录”到USB存储设备上真是让人厌烦,因为我总是找不到所需的那个U盘,而相比之下,我的电脑在我周围的混乱环境中更难丢失... :-(


1我之前走过这条路,真是太棒了。 - Organic Marble
1我喜欢使用单独的分区,每个驱动器都有一个,这样可以更容易地安装到其他驱动器或将整个驱动器安装到闪存驱动器上。https://help.ubuntu.com/community/Grub2/ISOBoot 示例:https://help.ubuntu.com/community/Grub2/ISOBoot/Examples 我发现在挂载分区之前正确获取路径以及获取详细的引导参数是使其正常工作的两个主要问题。路径甚至可能会因为插入闪存驱动器而改变。查看ISO文件以查看其引导段落和路径可以帮助您找出详细信息。 - oldfred
1我以前经常使用这种“grub-n-iso”方法,效果很好 :-) 但现在我在另一台电脑上测试iso文件,并且使用mkusb从iso文件克隆到快速USB3闪存盘,或者创建持久化的live USB闪存盘。(我把我的USB闪存盘存放在一个小塑料盒里。) - sudodus
VBox可以很好地运行ISO文件,退出时使用保存机器状态功能。MultiBootUSB具有拖放ISO启动选项,而QEMU与虚拟机管理器将快速运行ISO文件。 - C.S.Cameron
1目前只能使用Grub2 2.02来循环挂载ISO文件。Grub2 2.04会出现内存不足的错误。https://bugs.launchpad.net/ubuntu/+source/grub2/+bug/1851311 Ubuntu 18.04仍然使用Grub 2.02版本。 - oldfred
7个回答

确保您使用的是先前或更高版本,因为grub 2.04中存在一个错误
嗯,将ISO文件添加到grub的基本步骤对于UEFI和BIOS机器是相同的:编辑/etc/grub.d/40_custom文件,在文件底部添加一个menuentry项(此示例中使用GParted)。
menuentry "GParted Live ISO" {
}

现在我们要添加一个变量,其中包含我们存储ISO的目录(到目前为止,与BIOS机器没有任何区别:还不错)。
menuentry "GParted Live ISO" {
  set GPartedISOFile="/opt/Live-ISOs/gparted-live-0.31.0-1-amd64.iso"
}

我使用/opt来存储这些文件,因为我不喜欢在我的机器根目录下创建目录,而根据Linux文件系统层次结构,可选软件应该放置在那里。
在添加loopback变量之前,我们需要找出文件存储在哪个硬盘上,所以我们执行以下命令:df --output=source /opt/Live-ISOs/gparted-live-0.31.0-1-amd64.iso | tail -1,在我的机器上输出结果是:/dev/sdb2
然而,grub使用(hdX,Y)表示法,这就是UEFI和BIOS机器之间的区别所在!现在重新启动您的机器,进入grub菜单并按下C:这将带您进入grub命令提示符,其中包含与您习惯的不同的命令,但您只需要一个命令:ls。
在我的机器上,输出结果是:
(hd0) (hd1) (hd1,gpt3) (hd1,gpt2) (hd1,gpt1) (hd2) ... (hd3) ...

哎呀?4个驱动器?我只有3个!而且在BIOS中不是`(hd1,4)`这一行,而是在UEFI中是`(hd1,gpt3)`,而且`(hd0)`根本没有分区!
嗯,显然当NVRAM的一部分被用作存储并显示为`(hd0)`时,你需要从1开始编号你的驱动器!而所有关于引导ISO文件的信息都说你必须从0开始编号(在BIOS机器上这总是正确的,但在某些UEFI机器上不一定如此!)
所以`loopback`的值变成了`(hd2,gpt2)$GPartedISOFile`,因为我的机器上的ISO文件是`/dev/sdb2`(第二个驱动器`hd2`,第二个分区`gpt2`):
menuentry "GParted Live ISO" {
  set GPartedISOFile="/opt/Live-ISOs/gparted-live-0.31.0-1-amd64.iso"
  loopback loop (hd2,gpt2)$GPartedISOFile
}

另一个区别是在BIOS机器上,linuxinitrd被称为UEFI机器上的linuxefiinitrdefi,这就是我们的最终结果。
#!/bin/sh
exec tail -n +3 $0
# This file provides an easy way to add custom menu entries.  Simply type the
# menu entries you want to add after this comment.  Be careful not to change
# the 'exec tail' line above.

menuentry "GParted Live ISO" {
  set GPartedISOFile="/opt/Live-ISOs/gparted-live-0.31.0-1-amd64.iso"
  loopback loop (hd2,gpt2)$GPartedISOFile
  linuxefi (loop)/live/vmlinuz boot=live components config findiso=$GPartedISOFile ip=frommedia toram=filesystem.squashfs union=overlay username=user
  initrdefi (loop)/live/initrd.img
}

现在保存文件,并使用以下命令更新 grub:
update-grub

在完成上述操作之后,重新启动,进入GRUB菜单,选择GParted Live ISO,您现在可以轻松地启动ISO,而无需再次寻找USB闪存驱动器!

:-)

CloneZilla Live示例(适用于this question

menuentry "CloneZilla ISO" {
  set ISOFile="/opt/Live-ISOs/clonezilla-live-20170905-zesty-amd64.iso"
  loopback loop (hd2,gpt2)$ISOFile
  linuxefi (loop)/live/vmlinuz boot=live components config findiso=$ISOFile ip=frommedia toram=filesystem.squashfs union=overlay
  initrdefi (loop)/live/initrd.img
}

你有没有安装好Clonezilla?它有点不同,如果你还没搞清楚的话,我可以告诉你怎么做。 - Organic Marble
1我打算为那些“给我代码”的人明天再发布另一个答案... @OrganicMarble - Fabby
+1 但现在可能可以安全地从 update-grub2 中删除 2 - WinEunuuchs2Unix
@WinEunuuchs2Unix 这个在我的历史记录里… 我只需输入 upd↑ 然后复制粘贴。谢谢提醒,已更新! - Fabby
1在GRUB 2.04中,在第一个menuentry之前添加rmmod tpm到grub.cfg将解决使用UEFI引导ISO文件的问题。 - C.S.Cameron

另一种方法是将一个配置文件添加到40_custom中,就像这样:
menuentry 'Live ISOs on SSD' {
configfile (hd0,3)/ISO/livecdimage.cfg
} 

menuentry 'Live ISOs on HDD (boot on SSD)' {
configfile (hd1,3)/ISO/livecdimage.cfg
} 

我这样做是因为每当我更新ISO时,我总是忘记运行sudo update-grub。上述条目永远不需要更改,我只需编辑livecdimage.cfg,它与任何40_custom具有相同的格式,但没有标题行,并且位于我的ISO分区中的/ISO文件夹中。
我还会添加toram作为另一个启动参数,并在带有Nvidia的系统上添加nomodeset启动参数。但仍然经常需要卸载/isodevice。
无法卸载isodevice,卸载ISO https://bugs.launchpad.net/ubuntu/+source/ubiquity/+bug/1155216
sudo umount -l -r -f /isodevice

这是我的livecdimage.cfg文件的一部分

# livecdimage.cfg
# Add this to 40_custom to load this file:
# menuentry 'Live ISOs' {
# configfile (hd1,3)/iso/livecdimage.cfg
#} 
# Add iso names to livecdimage.cfg
#for i in `ls *.iso`;do echo "# "$i>>livecdimage.cfg; done;

menuentry "Ubuntu 16.04.4 xenial amd64" {
    set isofile="/ISO/ubuntu-16.04.4-desktop-amd64.iso"
    loopback loop (hd0,3)$isofile 
    linux (loop)/casper/vmlinuz.efi boot=casper iso-scan/filename=$isofile toram
    initrd (loop)/casper/initrd.lz
}

menuentry "Ubuntu 18.04 Bionic amd64" {
    set isofile="/ISO/bionic-desktop-amd64.iso"
    loopback loop (hd0,3)$isofile 
    linux (loop)/casper/vmlinuz.efi boot=casper iso-scan/filename=$isofile toram
    initrd (loop)/casper/initrd.lz
}

# spacer line
menuentry " " {
set root= 
}

menuentry "Reboot" {
    reboot
}

menuentry "Halt" {
    halt
}

1我喜欢重新启动和停止的那些! :-) +1 你为什么添加insmod? 你也可以在聊天中提醒我 - Fabby
可能不需要inmod。使用grub2时,一些功能是内置的,而另一些是通过addin(即insmod)添加的。可能在开始时我需要insmod gpt,因为我在2010年或之前开始使用gpt,当时个人电脑还是UEFI,而grub2只适用于BIOS/MBR,尽管可以通过BIOS引导gpt。 - oldfred
谢谢你的回答。那么,把那些句子从回答中删除岂不是更好? - Fabby
1让我编辑自己的段落并查看 18.04 是否能启动。我预计会成功。我还想更新我的 gparted ISO 启动项,目前非常陈旧,稍后回来。 - oldfred
1启动正常。我忘记了我插着我的18.04闪存驱动器,它在我的系统上变成了hd0,所以当启动时,我必须手动编辑条目将其向上移动一个hdX以获得正确的驱动器。我的gparted .25引导没有通过简单更改为.30而起作用。我不得不查看ISO并查看其grub.cfg,并使用那些参数和grub的循环命令,然后它才起作用。 - oldfred

mkusb多重引导黑客

由于mkusb具备对BIOS和UEFI的能力,它成为自定义启动驱动器项目的良好基础。

该黑客可以引导多个ISO文件,包括Windows安装程序,并具有grub2菜单。

大多数操作系统的grub2菜单项可通过Google搜索获得,超出了本回答的范围。

mkusb defaults

创建持久化 USB 驱动器时,请使用 mkusb 默认设置。

mkusb use defaults again

如果不确定,请使用mkusb持久性默认设置,分区大小可以稍后调整,但需要时间。

DUS Console

安装后的DUS控制台。

GParted Before

GParted 在分区修改之前。

Gparted after

Gparted修改后 - 用一个FAT32分区覆盖sdb4(ISO9660操作系统分区)和sdb5(ext2 casper-rw分区),以用于持久化文件。

Persistence partition

持久分区 - 为每个需要持久性的操作系统创建一个唯一命名的文件夹。

Persistence folder

持久化文件夹 - 在每个持久化文件夹中添加一个casper-rw文件和可选的home-rw文件。可以通过重命名casper-rw文件来创建home-rw文件。home-rw文件类似于完整安装中的独立home分区,可以在版本升级后重复使用。

ISO folder

在NTFS usbdata分区上创建一个文件夹,用于存放ISO文件。

ISO folder contents

将一些ISO文件添加到ISO文件夹中。

GRUB location

grub.cfg位置

grub.cfg

编辑 grub.cfg 文件以循环挂载 ISO 文件。如果需要持久性,请包括:persistent persistent-path=/<persistent-folder-name>/。在第一个 menuentry 之前的 grub.cfg 中添加 rmmod tpm。 编辑 18.04+ 在 grub 中指定 vmlinuz 而不是 vmlinuz.efi,以及 initrd 而不是 initrd 或 initid.lz。

sudo parted -ls  /dev/sdb

sudo parted -ls /dev/sdb

sudo lsblk -f  /dev/sdb

sudo lsblk -f /dev/sdb
如果需要Windows安装程序,最简单的方法可能是使用mkusb的“提取Windows安装程序”功能(我不得不手动将Windows ISO提取到TAR文件中)。

mkusb Windows Installer

安装后,创建一个用于ISO文件的文件夹,如果需要的话,还可以创建持久化文件夹(类似上述步骤)。

mkusb Windows grub

编辑/boot/grub/grub.cfg文件以循环挂载任何ISO文件并指定任何持久化文件夹。
(尚未找到循环挂载Windows ISO文件的方法)。
如果以上内容用作USB存储设备,可以用它来引导存储在仅有Windows的计算机上的ISO文件。在内部驱动器上不需要Grub。

怎样把它们重新存回硬盘/固态硬盘(HDD/SDD)呢?这个问题是关于不想使用USB闪存驱动器存储吗?或者我错过了什么吗? - Fabby
1@Fabby,这不仅适用于USB闪存驱动器。如果您有一个新的SATA驱动器,您可以按照此答案中描述的方式开始,并让mkusb安装其强大的引导系统,该系统在UEFI和BIOS模式下均可正常工作。这个SATA驱动器可以内部安装或通过USB或eSATA外部连接。您可以通过'grub-n-iso'添加“传统安装系统”和新的ISO文件以进行引导。 - sudodus
好的,我还是不明白:我想将这些ISO文件放在/opt/目录下。我该怎么做呢?(虽然我很感谢你的努力...) - Fabby
1@Fabby:我认为,与其按照上面所示创建一个新的文件夹来存放ISO文件,不如在grub.cfg中指定/opt/目录下的ISO文件位置,这样,U盘上的grub可以引导硬盘上的ISO文件。我会尝试一下这个方法。 - C.S.Cameron
@Fabby:如果ISO文件位于内部驱动器的/opt/目录下,那么您在内部驱动器上使用的相同菜单项也可以在外部驱动器上使用。将grub引导到USB存储设备上可能有一些优势,比如不会过度拥挤或破坏内部grub菜单。 - C.S.Cameron
我有3个内部驱动器。外部驱动器仅用于备份。 - Fabby

三个简单步骤

将ISO添加到grub菜单并从中引导。

首先,安装grml-rescueboot

打开终端并输入:

sudo apt install grml-rescueboot

第二步,将iso文件移动到/boot/grml/目录下。
在同一个终端中输入:
sudo mv ~/Downloads/<filename.iso> /boot/grml/

第三步,更新grub

在同一个终端中输入:

sudo update-grub

根据需要重复第二步和第三步

不要忘记从/boot/grml中删除过时的ISO文件。

参考:Ubuntu关于Grub2 ISO引导的帮助

注意

grml-rescueboot无法与所有live ISO文件一起使用。例如,gparted live ISO无法使用。请参阅使用grml-rescueboot无法启动Gparted Live

希望这有所帮助


1/boot 不是放它们的最糟糕的地方。抱歉,我查看了grml,应该提到它。不过还是要给你加1分,因为你努力了。 - Fabby
感谢 @Fabby 的点赞!这可能不是最好的方法,但在我看来,这似乎是最简单的方式。 - user68186
1这就是为什么+1:对于非技术用户来说,是一个很好的答案。 - Fabby
非常简单的解决方案。经过测试,它有效。问题是,你必须将这个图像放入/boot,并且引导分区通常只有1GB。所以你可能需要使用较小的Linux发行版。 - luke
@luke 在默认的Ubuntu安装中,/boot不是一个单独的分区,除非你选择LUKS加密。我的设置没有任何加密,所以这不是一个问题。 - user68186
好知道。是的,我有加密分区。所以当你使用LUKS加密时,限制引导分区大小的问题才会出现。谢谢你告诉我真相 :) - luke

MultiBootUSB - QEMU

如果你想要以最简便的方式引导ISO文件,并且不需要持久性,MultiBootUSB提供了QEMU选项:

  • 启动MultiBootUSB并选择“Boot ISO/USB”选项卡。

  • 将ISO文件拖放到“Select image”区域。

  • 选择RAM大小并点击“Boot ISO”按钮。

你无需编辑grub.cfg甚至注销。

MultiBootUSB-QEMU


太棒了!我等会儿要试试这个! - Fabby
@Fabby:MBUSB有Windows版本和Linux版本。我无法让Windows版本启动ISO文件,只能启动USB设备。对我来说,Linux版本9.2.0非常好用。 - C.S.Cameron

简单的mkusb ISO多重引导

如果您不需要多重持久性,那么在mkusb闪存驱动器上多重引导操作系统ISO非常容易。

使用mkusb制作一个持久性USB驱动器,选择默认的操作系统,https://help.ubuntu.com/community/mkusb

在usbdata分区sdx1中创建一个名为ISOs的文件夹。

将要引导的ISO文件添加到此文件夹中。

在/sdx3/boot/grub/grub.cfg中添加菜单项以循环挂载ISO文件。

示例:

menuentry "Ubuntu-18.04 64-bit ISO" {
    set root=(hd0,1)
    set isofile="/ISOs/ubuntu-18.04-desktop-amd64.iso"
        loopback loop $isofile
        linux (loop)/casper/vmlinuz boot=casper iso-scan/filename=$isofile splash --
        initrd (loop)/casper/initrd.lz
}

menuentry "GParted 64-bit ISO" {
    set root=(hd0,1)
    set isofile="/ISOs/gparted-live-0.31.0-1-amd64.iso"
    loopback loop $isofile
    linux (loop)/live/vmlinuz boot=live union=overlay username=user config components noswap noeject toram=filesystem.squashfs ip='' nosplash findiso=$isofile splash --
    initrd (loop)/live/initrd.img
}

menuentry "Clonezilla 64-bit ISO" {
    set root=(hd0,1)
    set isofile="/ISOs/clonezilla-live-2.5.5-38-amd64.iso"
    loopback loop $isofile
    linux (loop)/live/vmlinuz boot=live live-config nolocales edd=on nomodeset ocs_live_run=\"ocs-live-general\" ocs_live_extra_param=\"\"   ocs_live_keymap=\"\" ocs_live_batch=\"no\" ocs_lang=\"\" vga=788   ip=frommedia nosplash toram=filesystem.squashfs findiso=$isofile splash --
    initrd (loop)/live/initrd.img
}

这可能是您需要的多启动解决方案。

https://www.ventoy.net/en/index.html

这个可启动的USB制作工具会在USB驱动器中创建两个分区。一个是32MB FAT 32 EFI分区,另一个是与USB驱动器剩余空间大小相等的exfat分区。您可以将任意数量的ISO文件(包括Windows)复制到根目录或任何子文件夹中。您还可以将此分区用于正常存储。
在启动菜单中选择此USB,它将显示所有支持的ISO文件列表供您选择。根据我的经验,它适用于Ubuntu、Kubuntu、Mint、Clonezilla和Windows。

Ventoy