I have standard dual-boot system: Ubuntu and Windows. Grub is configured to launch Windows by default.
Is there a way to create some kind of link in Windows, that would:
- restart Windows
- boot into Ubuntu
I have standard dual-boot system: Ubuntu and Windows. Grub is configured to launch Windows by default.
Is there a way to create some kind of link in Windows, that would:
You don't need to modify /boot/grub/grub.cfg
like Michal Hagara suggested. This could break Ubuntu if you install a new kernel and doesn't update the e:\home\user\Grubshift\ubuntudefault\grub.cfg
.
All you need to do is to create/copy a file /boot/grub/grubenv
with following content
# GRUB Environment Block
next_entry=2
###########################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################
Where next_entry
is the line of the next grub menu entry which should be started next time (starting from zero). So next_entry=2
would be the 3th line.
Grub will automatically remove the value after boot so next time you'll boot into your default OS again.
This is how grub-reboot
works.
Here is what I have in mind:
I can be completely wrong with this approach, but I can't see, why it shouldn't work.
EDIT:
And also there is: http://www.paragon-drivers.com/extfs-windows/ which I have never tried.
1.Shortcut to restart Windows and boot Ubuntu
OK, down side of this is we will have to modify grub.cfg (/boot/grub/grub.cfg) directly (it is advised against - https://askubuntu.com/a/437341/402801),because there is no way to run update-grub
from Windows... if you can live with that read further.
/home/user/Grubshift
with 3 sub directories: backup (for backing up actual /boot/grub/grub.cfg), ubuntudefault (for storing grub.cfg with Ubuntu as default), windowsdefault (you've got the idea)After installation, Ubuntu is set as default, so copy that grub.cfg
to your desired directory. I've got "Windows as default" config by modifying GRUB via grub-customizer (it's safer in my opinion), after that copy Windows grub.cfg
to your desired directory
After that, open notepad and insert:
copy e:\boot\grub\grub.cfg /y e:\home\user\Grubshift\backup
copy e:\home\user\Grubshift\ubuntudefault\grub.cfg /y e:\boot\grub
shutdown /r /t 0
/y
- option of copy
command, suppresses prompting to confirm you want to overwrite an existing destination file
/r /t 0
- options of shutdown, 1. means reboot, 2. means immediately, without ugly messages popping up
Modify the path accordingly !!!
*.bat
shift.bat
, right click on shorctur --> properties--> shortcut tab --> Run:minimized (that will get rid of CMD popping up)I have tried this at least 8 times, setting Windows as default
with grub-customizer
...
I'm not saying it's safe, but HEY!, we are messing with bootloader... that isn't safe
When it's fully working, we can get rid of GRUB menu completely, because it will always boot into right OS...
To sum it up: System reboots default to last active, reboots from windows to linux and vice versa using a simple script.
Under linux:
GRUB_DEFAULT=saved
and GRUB_SAVEDEFAULT=true
in /etc/default/grub sudo update-grub
see http://www.paragon-drivers.com/extfs-windows/
If /boot/grub/grubenv doesn't exist, create it using the answer from Germar
@echo off
"C:\Program Files (x86)\Paragon Software\ExtFS for Windows\extmounter" /mount disk1 L:
:CheckForFile
IF EXIST "L:\boot\grub\grubenv" GOTO FoundIt
GOTO CheckForFile
:FoundIt
sed -i -e '/next_entry/c\next_entry=0' L:/boot/grub/grubenv
"C:\Program Files (x86)\Paragon Software\ExtFS for Windows\extmounter" /umount disk1 L:
echo press enter to reboot
pause
shutdown -r -t 00
/mount disk1 L:
with something specific to your system. You can find available disks using the extmounter /list
command and the drive letter. Also, L:
must not be already taken.reboot-linux.bat
run as administrator
to execute it sudo sed -i -e '/next_entry/c\next_entry=2' /boot/grub/grubenv
sudo reboot
next_entry=2
with whatever your windows entry is. ~/reboot_windows
and mark as executable: chmod +x ~/reboot_windows
I use Arch instead of Ubuntu but the GRUB configuration should be the same.
What I don't really like about the previous anwsers is that they:
grub.cfg
file directly, which is intended for permanent changesgrubenv
in a way that corrupts the GRUB environment block, which results in warnings on Linux boot and breaks the grub-editenv
commandSo first of all you need to setup GRUB to remeber the last system booted to (it's convenient for reboots anyway):
GRUB_DEFAULT=saved
and GRUB_SAVEDEFAULT=true
in
/etc/default/grub
sudo update-grub
(on Arch it's grub-mkconfig
)There's this convenient command called grub-reboot
which lets you one-shot boot into Windows. Very handy. Note that this keeps the last saved entry in GRUB, so when you go like Linux>grub-reboot to Windows>Windows>reboot it will reboot you back to Linux. To override this (unwanted IMO) behavior add another command afterward like this:
grub-reboot $name
grub-editenv /boot/grub/grubenv set saved_entry=$name
where $name
is the name of Windows as it appears in GRUB. I explain it in detail below. After running these commands reboot the system.
So I decided to investigate what the Linux script does. It calls grub-editenv
and sets the value of next_entry
to the desired OS. I spent a few hours doing trial and error editing the grubenv
file trying to replicate the result and managed to come up with a solution. It turns out that the GRUB environment block should always be kept exactly 1024 bytes long, that's why there are #
signs at the end by default. Here's my PowerShell script. It might be a bit verbose but it gets the job done correctly.
function Get-ArrLength {
param (
[Parameter(Mandatory=$true,ValueFromPipeline=$true)]
[string[]]$arr
)
$text = [string]::Join("`n", $arr)
($text | Measure-Object -Character).Characters
}
mountvol P: /S
P:
cd grub
cp grubenv grubenv.bak
$name = "Arch Linux"
$name_len = ($name | Measure-Object -Character).Characters
$arr = cat grubenv
$original_length = Get-ArrLength $arr
$arr = $arr -replace "next_entry=","next_entry=$name"
foreach ($a in $arr) {
if ($a -match "saved_entry=") {
$arr[$arr.IndexOf($a)] = "saved_entry=$name"
}
}
$candidate_length = Get-ArrLength $arr
if ($candidate_length -gt $original_length) {
$arr[$arr.Count-1] = $arr[$arr.Count-1].SubString(0,$arr[$arr.Count-1].Length-($candidate_length-$original_length))
} elseif ($candidate_length -lt $original_length) {
$arr[$arr.Count-1] = $arr[$arr.Count-1] + "#" * ($original_length-$candidate_length)
}
$contenttext = [string]::Join("`n", $arr)
sc grubenv ([byte[]][char[]] "$contenttext") -Encoding Byte
Restart-Computer
$name
with the name of your installation
as it appears in GRUB. If it's within a GRUB subfolder, use the >
character as a path separator like so:
$name="subfolder_name>OS_entry_name"
. Instead of names you can also
use numbers where 0
is the first item as it appears in the GRUB
menu but going with names is more versatile should the entries order
change.P:
in the lines mountvol P: /S
and the following
is completely arbitrary and you can change it to any drive letter
that's available on your Windows system.Restart-Computer
if you only want to change the GRUB entries and later reboot manually.grubenv.bak
so if anything goes wrong you can always restore it by simply copying it back to grubenv
.