如何让grub2在下一次启动时仅引导不同的选项?

我正在设置一个双启动的无头Linux/Windows机器。我希望这台机器大部分时间都能启动到Ubuntu,只有在需要在Windows中测试一些东西时才会启动到Windows。
我已经安装了Windows和Ubuntu,目前每次启动都是进入Ubuntu。我想要能够告诉它在下一次启动时启动到Windows,并且当我从Windows重新启动时,系统能够返回到启动Ubuntu的状态。
我找到了Grub Legacy - section 4.3.1 - Booting once-only,但我使用的是Ubuntu 14.04服务器,它有更新版本的grub。根据我所了解,我需要对/etc/default/grub进行一些更改,并在想要启动到Windows时使用sudo grub-set-default命令。
我认为这些更改应该从将以下内容添加到/etc/default/grub开始:
GRUB_DEFAULT=saved
GRUB_SAVEDEFAULT=false

每当对/etc/default/grub进行更改时,我知道接下来需要运行
sudo update-grub,这将产生以下结果:
Generating grub configuration file ...
Found linux image: /boot/vmlinuz-3.13.0-43-generic
Found initrd image: /boot/initrd.img-3.13.0-43-generic
Found linux image: /boot/vmlinuz-3.13.0-32-generic
Found initrd image: /boot/initrd.img-3.13.0-32-generic
Found memtest86+ image: /boot/memtest86+.elf
Found memtest86+ image: /boot/memtest86+.bin
Found Windows 7 (loader) on /dev/sda1
done

由于Windows是该列表中的第7个选项,我相信我应该运行sudo grub-set-default 6(基于0的计数)- 这样做正确吗?在系统已经启动之后,是否有其他方法可以获得引导选择的编号列表?

另外,在/etc/default/grub文件中的这些行是否足以实现此行为,还是我需要添加其他配置?

4个回答

你需要确保在你的 grub 配置文件中有 GRUB_DEFAULT=saved(这是自动生成的,你可以通过编辑 /etc/default/grub 来更改它的一部分)。使用 sudo update-grub 使更改生效,然后使用 sudo grub-reboot $1
grep -i "menuentry '" /boot/grub/grub.cfg

将为您提供可剪切粘贴的菜单项,每个菜单项价格为1美元。或者,如您所指出的选项从零开始索引,因此第n个菜单项可以通过将(n-1)传递给grub-reboot来获取。

参见:

我没有测试过,因为我没有安装'Windows 7'。


谢谢,我觉得这就是我需要的(还有我在https://help.ubuntu.com/community/Grub2找到的额外细节)。 - cwd
1如果你在不将行改为GRUB_DEFAULT=saved的情况下尝试了这个操作,那么你之后必须手动进行操作,就像Grub2的第二段中所解释的一样,然后执行grub-set-default 0; grub-reboot 0 - rubo77
4显示条目的编号的命令:grep -i "menuentry '" /boot/grub/grub.cfg|sed -r "s|--class .*$||g"|nl -v 0 - rubo77
4根据https://askubuntu.com/questions/838704/grub-reboot-to-specific-kernel的建议,`/ boot / grub / grub.cfgsubmenu下的menuentry必须作为SUBMENU>MENUENTRY传递给grub-reboot。因此,例如,使用类似于@rubo77的bash技巧,我想要启动menuentry 7,但是这个条目位于顶级菜单中的第二个submenu`下,所以我需要传递'1>6'(使用单引号避免shell解释>)。 - trent.sol
3警告:如果您使用BTRFS分区启动,此方法将无效。Grub在引导Windows时需要能够写入grubenv文件,而无法写入BTRFS分区。该文件通常存储在/boot/grub目录下,并可通过grub-editenv命令查看。我通过将BTRFS分区挂载到根目录“/”,将EXT4分区挂载到“/boot”,然后将EFI分区挂载到“/boot/efi”的方式修复了我的系统。 - nathan
2注意:对于启动时可见的 grub 选项,你只需要 行号 减去 1,因此如果 Windows 是第三行,请使用 sudo grub-reboot 2; reboot - rubo77

这正是grub2-once所做的事情。请尝试一下。似乎grub2-once只适用于SUSE的Linux发行版。
shiraz-1:~/:[0]# grub2-once --list
     0 SLES 15-SP1
     1 Advanced options for SLES 15-SP1>SLES 15-SP1, with Linux 4.12.14-195-default
     2 Advanced options for SLES 15-SP1>SLES 15-SP1, with Linux 4.12.14-195-default (recovery mode)
     3 Advanced options for SLES 15-SP1>SLES 15-SP1, with Linux 4.12.14-95.54.1.19924.5.TEST.1167133-default
     4 Advanced options for SLES 15-SP1>SLES 15-SP1, with Linux 4.12.14-95.54.1.19924.5.TEST.1167133-default (recovery mode)

shiraz-1:~/:[0]# grub2-once 3
shiraz-1:~/:[0]# reboot

如何安装grub2-once?我在Ubuntu 20.04中找不到它。也许只有OpenSuSE有? - rubo77
很不幸,是的。这是由suse.com的员工编写的Perl脚本。您可以通过在http://www.rpmfind.info/上搜索最新的opnesuse发行版的grub2软件包来找到它。 - firo
3所以最好只使用 sudo grub-reboot 3; reboot - rubo77

awk -F\' '/^menuentry / {print $2}' /boot/grub/grub.cfg|cat -n|awk '{print $1-1,$1="",$0}'

那会给你可用的 grub 引导菜单选项的数字和名称。

尝试在您的Ubuntu系统上安装grub-customizer(以下是安装指南)。这个图形界面工具将为您提供一组漂亮的选项,您可以使用它来配置GRUB设置,包括启动选项的名称和顺序、默认系统、屏幕分辨率、字体、背景等等...
我不确定它是否有直接设置您想要的功能,但至少它可以显示操作系统的编号。它们也可以通过名称进行引用,我想。
如何安装grub-customizer:
sudo add-apt-repository ppa:danielrichter2007/grub-customizer
sudo apt-get update
sudo apt-get install grub-customizer

(来源:launchpad - daniel richter

我看到了那个工具,但我正在使用Ubuntu 14.04服务器(无图形界面),所以我希望有一个命令行解决方案。 - cwd
哦,我不知道这个。我使用的是14.10标准(Unity),我个人更喜欢使用图形用户界面来完成这样的工作。你知道这个网站吗?它描述了你在问题中提到的内容,但如果与你的第一个来源有所不同,也许你可以在那里找到你需要的确切信息。 - Byte Commander
-1 - 我给你的回答点了个踩,因为我怀疑你是否真正阅读了问题。我可以理解你可能忽略了问题中的“Ubuntu服务器”,但你在上一条评论中贴了与我在问题中提到的相同链接... - cwd
糟糕。但是你认为每次我写新评论或回答时都会重新阅读整个问题和以前的帖子,检查每个链接吗?此外,你也可以在服务器发行版上安装桌面环境!我承认我不是专家(还没有),但至少我尽力在我能帮助别人的地方,即使答案并不总是100%正确或有用。你应该庆幸有人试图帮助你解决这个问题,但如果你想激怒我,你成功了。最后一件事:你提到了GRUB_SAVEDEFAULT=false,但我在我们的链接中找不到这个。而且你忘记了其他提到的行! - Byte Commander