如何从Ubuntu重新启动到Windows?

我正在寻找一种从Ubuntu到Windows重新启动的方法,这是一个安装有10.10/Vista双重引导系统的情况。具体用例是,我希望能够ssh进入运行中的Ubuntu实例并发出一个命令,将直接启动重启进入Windows。

我找到了一篇有希望的博文,但其中建议的脚本无法工作:

#!/bin/bash

WINDOWS_ENTRY=`grep menuentry /boot/grub/grub.cfg  | grep --line-number Windows`
MENU_NUMBER=$(( `echo $WINDOWS_ENTRY | sed -e "s/:.*//"` - 1 ))
sudo grub-reboot $MENU_NUMBER
sudo reboot

man grub-reboot没有太大帮助,但它似乎把我引导到了正确的方向:

设置GRUB的默认引导项, 仅适用于下一次启动

WINDOWS_ENTRY=`grep menuentry /boot/grub/grub.cfg  | grep --line-number Windows`
MENU_NUMBER=$(( `echo $WINDOWS_ENTRY | sed -e "s/:.*//"` - 1 ))
echo $MENU_NUMBER

这返回了预期的值,但在重新启动后,第一个菜单项仍然被突出显示。有没有关于为什么这不起作用或其他解决方案的建议?

如果你将Windows的GRUB引导行复制到GRUB菜单列表的顶部,那么每次启动时Windows将成为默认加载项。如果你在Ubuntu中通过SSH登录,然后运行sudo reboot now命令,机器将重新启动并加载GRUB列表中的第一项。 - karthick87
当然可以,但我很少启动那个Windows分区。我不想将其设为默认选项。 - andrewsomething
7个回答

  • 首先,你需要编辑grub。

    sudo gedit /etc/default/grub
    
  • 在文件中找到GRUB_DEFAULT=0这一行,并将其修改为GRUB_DEFAULT=savedalt text

  • 使用以下命令更新grub。

    sudo update-grub  
    
  • 现在创建一个脚本文件。

    sudo gedit switch-to-windows.sh
    
  • 然后添加以下内容。

    #!/bin/bash
    WINDOWS_ENTRY=`grep menuentry /boot/grub/grub.cfg  | grep --line-number Windows`
    MENU_NUMBER=$(( `echo $WINDOWS_ENTRY | sed -e "s/:.*//"` - 1 ))
    sudo grub-reboot $MENU_NUMBER
    sudo reboot
    
  • 将脚本文件设置为可执行。

    sudo chmod +x switch-to-windows.sh
    
  • 现在你可以从终端运行这个脚本来重启进入Windows。

    ./switch-to-windows.sh
    
  • 或者你可以在终端中执行以下命令

    sudo grub-reboot X  
    
  • 其中X是你想要从GRUB菜单中重新启动的操作系统的menuentry位置(从0开始计数,第一个条目为0)。

举个例子:

  • 如果这是您的启动菜单,如果您想要启动到 Windows,您应该将 X 的值设为 5。
  • sudo grub-reboot 5

    alt text

  • 您还可以为上述命令创建一个启动器,这样双击启动器就可以重新启动到 Windows。

我可以让它工作一次。之后你必须输入密码。 - hashky
7你是怎么让 grub 看起来那样的? - Mandy
跟上面的问题有关吗?你是如何让食物看起来如此漂亮的呢? - Diego
5解决方案非常出色,但是由于我的菜单条目前有14个选项卡,使用标题而不是菜单条目编号效果更好。所以你可以用以下代码修改你的代码: #!/bin/bash WINDOWS_TITLE=grep -i 'windows' /boot/grub/grub.cfg|cut -d"'" -f2 sudo grub-reboot "$WINDOWS_TITLE" sudo reboot - Philippe Gachoud
Philippe Gachoud,请将您的回答变成一个答案!这是唯一有效的答案! - honi
1没有理由设置 GRUB_DEFAULT=saved,它会搞乱你的配置。grub-reboot 的作用是将 next_entry=ENTRY 写入 /boot/grub/grubenv。这与 saved_entry=ENTRY 不同。下一次重启时,grub 将读取 next_entry。如果没有将条目保存为 saved_entry=ENTRY 在 grubenv 中,后续的引导可能会失败。 - mook765
在我的Ubuntu 20.04系统中,有一些包含"menuentry"但并不是菜单项的行,所以MENU_NUMBER不正确。我认为另一个评论中提到的WINDOWS_TITLE方法现在更好地适用。 - Xor
对于Linux Mint 19.3(Ubuntu 18.04),我使用了相同的脚本,但将WINDOWS_TITLE行替换为:WINDOWS_ENTRY=$(grep -iE '^menuentry' /boot/grub/grub.cfg | grep -iE --line-number '*' | head -n 1) - lolsky

有一个 grub 命令可以这样做,就是 grub-reboot

看起来只有在你配置了 grub 以最后保存的项目启动时才能起作用。所以如果你还没有这样做,请修改 /etc/default/grub 并设置

GRUB_DEFAULT=saved

然后更新grub配置文件:
sudo update-grub

从现在开始,每次启动时,grub将启动上次使用的条目。
现在,如果您想预先设置下一次启动应该引导的系统,请使用
sudo grub-reboot ENTRY

其中ENTRY可以是相对于菜单项的数字(从0开始编号),也可以是一个确切的菜单项标题,例如

sudo grub-reboot "Microsoft Windows XP Professional (on /dev/sda1)"

这个命令可以很容易地作为启动器提供。
#!/usr/bin/env xdg-open
#
# save as ~/Desktop/reboot-into-windows.desktop
#

[Desktop Entry]
Version=1.0
Type=Application
Terminal=false
Exec=sh -c 'gksu "grub-reboot 2" && gnome-session-save --shutdown-dialog'
Name=Reboot into Windows
Icon=gnome-panel-launcher

但是我不知道它如何集成到系统菜单中。
你可以通过以下方式获取可用的菜单项标题:
sed -n '/menuentry/s/.*\(["'\''].*["'\'']\).*/\1/p' /boot/grub/grub.cfg 

1没有理由设置GRUB_DEFAULT=saved,这会搞乱你的配置。grub-reboot所做的是将next_entry=ENTRY写入/boot/grub/grubenv。而不是saved_entry=ENTRY。下一次重启将正常运行,因为grub会读取next_entry。如果在grubenv中没有保存条目作为saved-entry=ENTRY,那么随后的引导可能会失败。 - mook765

我觉得我找到了一个更好的方法,适用于那些想在本地电脑上进行操作而不使用ssh的人。
刚刚在webupd8上发布了一个通过Unity启动器选择重启到特定系统的解决方案。 请参阅http://www.webupd8.org/2011/05/custom-unity-launcher-to-reboot-in.html
我知道这并不完全符合问题的要求,但是以防以后有人有类似的问题,这可能会有所帮助。

对我来说,最好的方法是使用grub-reboot命令创建以下脚本。
#!/bin/bash 
WINDOWS_TITLE=$(grep -i 'windows' /boot/grub/grub.cfg|grep "^[^#;]"|cut -d"'" -f2) 
sudo grub-reboot "$WINDOWS_TITLE" 
echo "Your computer will reboot on ${WINDOWS_TITLE} in 3 seconds, press Ctrl+C if you want to abord it"
sleep 3 && sudo reboot


虽然这个链接可能回答了问题,但最好在这里包含答案的关键部分,并提供链接作为参考。仅有链接的答案可能会因为链接页面的变化而失效。- 来自评论 - undefined
你的回答可以通过提供更多的支持性信息来改进。请编辑以添加进一步的细节,比如引用或文档,以便他人可以确认你的回答是否正确。你可以在帮助中心找到关于如何撰写好回答的更多信息。 - undefined

我不确定这个方法在Ubuntu上是否百分之百有效,但我曾经在CentOS机器上成功实施过。
基本上,你需要告诉grub应该运行grub.conf中的哪个id号。可以通过以下方式找到id号:
echo `sudo grep ^title /boot/grub/grub.conf | grep -n Windows | cut -f 1 -d:`-1

在我的情况下,这将输出"4-1",因为我的grub.conf文件的第四个条目包含了"Windows"文本。(将此替换为您想要使用的实际条目名称(部分)。 然后,您可以将其输入到grub中:
echo "savedefault --stage2=/boot/grub/stage2 --default=4-1 --once" | sudo /sbin/grub

在下一次重启时,它应该自动引导到你所指定的条目。
这一切可以放在一个脚本中,如下所示:
#!/bin/sh
let NEWBOOT=`sudo grep ^title /boot/grub/grub.conf | grep -n Windows | cut -f 1 -d:`-1
echo Booting $NEWBOOT - `sudo grep ^title.\*Windows /boot/grub/grub.conf`
echo "savedefault --stage2=/boot/grub/stage2 --default=$NEWBOOT --once" | sudo /sbin/grub
sudo reboot

脚本将自动确定您的grub.conf中哪个条目对应于文本“Windows”,并将其提供给grub以告知下次启动时应加载什么,并重新启动您的计算机。
要使用图形界面,您可以在桌面上添加一个快捷图标来实现这一点。

1grub-legacy的配置文件是menu.lst,而不是grub.conf。对于grub2来说,它是grub.cfg,但你的第二个命令只适用于grub-legacy。 - psusi

只需编辑/boot/grub/grub.cfg文件,并将默认条目更改为您想要引导的条目。该值可以是条目的序号(从零开始,第一个为零)或者您可以用引号括起来的完整标题来表示所需的条目。

2不建议修改boot.cfg,它会在每次手动或自动的update-grub时被恢复。用户应该修改/etc/default/grub - enzotib
1@enzotib,因为更改只适用于下一次启动,所以没有必要以那种方式进行。 - psusi
2你忘了一次错误的编辑可能导致系统无法启动。 - enzotib
1@enzotib,不完全正确;grub2的一个美妙之处在于你总是可以在提示符下手动恢复。此外,破坏文件其他部分的危险是站不住脚的论点,如果默认行设置错误,最糟糕的情况就是它会默认选择第一项。 - psusi