How to change default boot option in grubenv

Sometimes I need to boot another kernel remotely, and I modify /boot/grub2/grubenv
saved_entry=8fxxxxxxxxxxxxxxxxxxxxxx23-6.0.13-300.fc37.x86_64
to choose different version of kernel, to modify ...-6.0.XX-300.fc37.. and it works fine. But I also have mirror disk in the server and menu also recognize it, when you do
grub2-mkconfig -o /boot/grub2/grub.cfg
but menu items will appear something like this
...Fedora 37 on sdb...
repeated a few times (probably because it has 3 kernel versions saved), so how to choose one of those menus remotely to reboot in the mirror of the system?

Are these the command you are looking for:

grub2-set-default
grub2-editenv

Do you maybe have a specific command line, to know how to define specific boot option?

I tried on my laptop:
awk -F\' '$1=="menuentry " {print $2}' /boot/grub2/grub.cfg
and got:

Windows Boot Manager (on /dev/nvme0n1p2)

and that is not the whole menu, just one, last entry.
Commandline grub2-set-default 2 should select menu item #3 but how to list menu items, as there are not listed any more in grub.cfg, like in the old times

I would start with grep -i title /boot/loader/entries/*.conf to find out what your choices are.

Edit: I see someone who typically knows more about this than I do, edited my post to insert the -i above. I’ve never seen a .conf file there in which title wasn’t all lower case (making the -i unnecessary). But I can’t say it never happens, so the -i can’t hurt.

That assumes you know what sequence the choices will appear in. That is possible to figure out, but generally not worth the trouble.

Instead, you can use the text of the choice rather than the number.

I hope you understand the file is expected to be exactly 1024 bytes long, so in modifying it, you are supposed to exactly preserve the length. That is why you should use the command line tools to modify it, rather than a text editor.

But ultimately, I don’t know what aspect of this you even have a question about, since you seem to know most of it already (unless it was just the grep command I gave above).

  1. How to know what choices are available: that grep command or similar awk construct (plus for non-fedora menu items, the command you already have).
  2. How that is selected by name (rather than number) inside /boot/grub2/grubenv (you seem to already know)
  3. How mechanically to modify that file preserving its length (you implied experience with that).
  4. Where those directories (/boot/loader/ and /boot/grub2) are on some server you have (if you don’t know, how can anyone tell you).
  5. Given the list of choices (1), which you want (you can’t be asking that).

When I look at the grub menu it seems the list is built from the bottom up in the order seen when I do ls /boot/loader/entries/, since that usually shows the highest numbered kernel entry at the bottom of that list.

Setting the index number to select the kernel to boot will change kernel every time a new kernel is installed.

If the same kernel is wanted for every boot then it is possible to do so with adding SAVEDEFAULT=true to the end of the /etc/default/grub file then running sudo grub2-mkconfig -o /boot/grub2/grub.cfg on that host. Once this is done then the selected kernel will always remain as the one booted, even with kernel upgrades, until the user selects a different kernel to boot from the grub menu.

This method sets the specific kernel and not the position within the grub menu as the choice. It also, since that kernel is booted, prevents that kernel from being removed with a kernel update in the future.

Note that once set this way, AFAIK the only way to change the kernel in use is to change the kernel booted from the actual grub menu which would require the user to be at the console when booting. Editing the grubenv file would allow you to make a change remotely but I am not comfortable with that for reasons noted above. The system also modifies the grubenv file with each boot to indicate status.

1 Like

Somehow I failed to parse the above description when I answered earlier. Rereading now, it is perfectly obvious what you said.

There is another drive in the same server that has a similar (or same) set of fedora versions as the disk that is selected for boot by the bios. That was all seen by the program that populated /boot/loader/entries so I assume (but you’ll need to check) you have .conf files in that directory for both the fedora versions in the regular location (sda I assume) and those in sdb.

So I think my answer was correct, even though I answered without understanding your question. You look at the title lines for the /boot/loader/entries/*.conf files for sdb to find which one you want to boot next and find the exact text of its title. The edit /boot/grub2/grubenv to select that for the next boot by title.

I half recall there is some way there to select a choice for one-time next boot, then revert to the usual default. I think that is what you would want, but if so I don’t really recall how. So instead, after booting the sdb copy you would need to revert that grubenv file. Depending on how things are set up, I’m not sure the /boot/ mounted when you are running on sdb will be the one on sda in which you need to revert that file.

1 Like

The problem is that boot entries from other disks are not listed in /boot/loader/entries so from what I understand grub2-mkconfig searches for all bootable OSes in all disks, and ads entries to grub.cfg, apart from the local boot entries. and then at boot time grub looks for boot entries is /boot/loader/entries on the fly + displays entries that are written in grub.cfg.

It used to be more straight forward with all entries in grub.cfg and one could just change boot # to boot different kernel/disk. But now I can’t find the way, to define it somehow

I don’t know awk so initially I just trusted that. But now I think you’re missing something important. Using grep simplistically would give messy output and a little extra content, but would identify what, if anything, you missed with awk

grep "menuentry " /boot/grub2/grub.cfg

Maybe I misunderstood what you meant there. I assume that means you are seeing such entries (if you connect an actual display on the server and look while booting), so those are coming either from /boot/grub2/grub.cfg or from /boot/loader/entries

But if your awk is correct, then not from /boot/grub2/grub.cfg and …

Not there either. So what are you really describing?

Maybe you mean: On some other computer under other conditions, there were those sdb entries in /boot/grub2/grub.cfg, but not on the server you’re currently trying to boot?

That would imply you need to manually construct the entry you want (not difficult since you should know some existing entry it should be similar to, plus you know what the differences should be).

Depending on how the mirror is set up (by drive rather than by partition), the partitions on the mirror may have the same UUIDs as on the main drive. In that case, the usual method of searching for partitions by UUID would not be valid, so in manually constructing an entry, you would want to specify by the absolute partition specifier, not UUID. But then you’d have the same issue in /etc/fstab which I assume should not differ between the main copy and the mirror.

So I guess I’m missing something more basic about what you hope to accomplish in booting a mirror (as I tried to answer the question asked about what to put into grubenv).

1 Like

@john2fx the top grep of menuentry was from my laptop. so it’s not the same machine.
And I’m not worried about using awk/grep… I can open and edit grub.cfg or grubenv files and check what’s inside. The problem is that live grub menu displays entries form /boot/loader/entries and whatever extra menuentries are listed in grub.cfg so for particular server I have following entries:

[root@srv /etc] grep -i menuentry /boot/grub2/grub.cfg |awk -F\' '{print $2}'

Fedora Linux 37 (Server Edition) (on /dev/sda3)
Fedora Linux 37 (Server Edition) (on /dev/sda3)
Fedora Linux 37 (Server Edition) (on /dev/sda3)
Fedora Linux 37 (Server Edition) (on /dev/sda3)
Fedora Linux 35 (Server Edition) (on /dev/sde5)
Fedora Linux 35 (Server Edition) (on /dev/sde5)
Fedora Linux 35 (Server Edition) (on /dev/sde5)
Fedora Linux 35 (Server Edition) (on /dev/sde5)
Fedora Linux 35 (Server Edition) (on /dev/sde5)
Fedora Linux 35 (Server Edition) (on /dev/sde5)
Fedora Linux 35 (Server Edition) (on /dev/sde5)
UEFI Firmware Settings

I presume that top one is with latest kernel, so less and less current lower I go. I also know that F36 changed system to put configs in /boot/efi for new installations, but for existing upgrades add extra .conf files in /boot/loader/entries
So say I want to boot top of the menu from /dev/sda3, what should I put in grubenv? As the live grub menu will display first 3 entries from /boot/loader/entries folder, and after all those menu items listed above.
I thought there is command-line ie grub2-set-default that I can list all menu-entries and than set default one (which I prefer) and reboot to that one. Even if I’m on site is still a drag to bring display, keyboard to the server and then reboot, when I need to check mirror disk if all is fine.

Does:
sudo grubby --set-default-kernel="kernel path"
or
sudo grubby --set-default-kernel-index="entry-index"

Work for what you’re trying to do?

You can get the info form sudo grubby --info=ALL

Edit: fixed --info

no output

Not sure what is the entry-index, I mean how to find it? kernel path not sure how to write it so it’s known for the grub on which disk/partition is located

That should be --info=ALL

That should provide the index and/or kernel path.

Thanks for the update. I do get output this time, but only list of menus from '/boot/loader/entries/` not from any other disk/partition in the system, so I still can’t choose menuentry from the mirror disk. I tried on different machines and same thing.

Does doing both together work?
sudo grubby --info=ALL | \grep 'title\|id' ; grep -i menuentry /boot/grub2/grub.cfg |awk -F\' '{print $2 "\n" $4}' | \grep ..

It does show all menu-entries, but what is the point if I can’t tell which index is which, so I can’t assign grub2-set-default…
But you actually give me an idea, so I just did
grubby --info=ALL
and I iterated +1 from the last index with
grub2-set-default 4
rebooted and it booted 1st menu-item from mirror disk. So yes, basically you just have to count menu-entries somehow, best manually from grub.cfg and /boot/loader/entries. I’ve thought that grubenv needed also saved_entry to be defined for the next boot, but it looks like grub2-set-default rewrites it and puts index keyword in

I thought grub2-set-default allowed for menu item titles or identifiers?
From the man page:

MENU_ENTRY is a number, a menu item title or a menu item identifier.

Yes, grub2-set-default does accept index, title or id, where; index is a number, title and id must be enclosed in quotes.

Any of the following results returned work:

sudo grubby --info=ALL | grep 'index=\|title=\|id=' && sudo grep -i "menuentry " /boot/grub2/grub.cfg | awk -F\' '{print "index=" NR+3 "\ntitle=\42" $2 "\42\nid=\42" $4 "\42"}'

Note: that I have used NR+3 in the awk statement as I know grubby list=ALL always returns 4 indexes (zero indexed) as Fedora maintains 3 Kernels and a rescue. Your mileage may differ.

The results returned from the above on my system is as follows.

Results
$ sudo grubby --info=ALL | grep 'index=\|title=\|id=' && sudo grep -i "menuentry " /boot/grub2/grub.cfg | awk -F\' '{print "index=" NR+3 "\ntitle=\42" $2 "\42\nid=\42" $4 "\42"}'
index=0
title="Fedora Linux (6.0.12-200.fc36.x86_64) 36 (Cinnamon)"
id="84221512f9d64d369eca65196b2466bf-6.0.12-200.fc36.x86_64"
index=1
title="Fedora Linux (6.0.11-200.fc36.x86_64) 36 (Cinnamon)"
id="84221512f9d64d369eca65196b2466bf-6.0.11-200.fc36.x86_64"
index=2
title="Fedora Linux (6.0.10-200.fc36.x86_64) 36 (Cinnamon)"
id="84221512f9d64d369eca65196b2466bf-6.0.10-200.fc36.x86_64"
index=3
title="Fedora Linux (0-rescue-84221512f9d64d369eca65196b2466bf) 36 (Cinnamon)"
id="84221512f9d64d369eca65196b2466bf-0-rescue"
index=4
title="Windows Boot Manager (on /dev/nvme0n1p1)"
id="osprober-efi-5818-3870"
index=5
title="Ubuntu Mint (on /dev/nvme0n1p2)"
id="osprober-gnulinux-/boot/vmlinuz-5.15.0-53-generic--102be97f-e68d-4b1d-9953-44dbf2336339"
index=6
title="Ubuntu, with Linux 5.15.0-53-generic (on /dev/nvme0n1p2)"
id="osprober-gnulinux-/boot/vmlinuz-5.15.0-53-generic--102be97f-e68d-4b1d-9953-44dbf2336339"
index=7
title="Ubuntu, with Linux 5.15.0-53-generic (recovery mode) (on /dev/nvme0n1p2)"
id="osprober-gnulinux-/boot/vmlinuz-5.15.0-53-generic--102be97f-e68d-4b1d-9953-44dbf2336339"
index=8
title="Ubuntu, with Linux 5.15.0-52-generic (on /dev/nvme0n1p2)"
id="osprober-gnulinux-/boot/vmlinuz-5.15.0-52-generic--102be97f-e68d-4b1d-9953-44dbf2336339"
index=9
title="Ubuntu, with Linux 5.15.0-52-generic (recovery mode) (on /dev/nvme0n1p2)"
id="osprober-gnulinux-/boot/vmlinuz-5.15.0-52-generic--102be97f-e68d-4b1d-9953-44dbf2336339"
index=10
title="Ubuntu, with Linux 5.4.0-131-generic (on /dev/nvme0n1p2)"
id="osprober-gnulinux-/boot/vmlinuz-5.4.0-131-generic--102be97f-e68d-4b1d-9953-44dbf2336339"
index=11
title="Ubuntu, with Linux 5.4.0-131-generic (recovery mode) (on /dev/nvme0n1p2)"
id="osprober-gnulinux-/boot/vmlinuz-5.4.0-131-generic--102be97f-e68d-4b1d-9953-44dbf2336339"
index=12
title="UEFI Firmware Settings"
id="uefi-firmware"

I do not have a mirror disk so I am unsure how those boot entries get listed or maintained, but hopefully some of the above is ‘food for thought’.

Good luck

1 Like

Thanks @stamper this shows correctly all the indexes. I wrote it down. So my output is

[root@cf etc]# sudo grubby --info=ALL | grep 'index=\|title=\|id=' && sudo grep -i "menuentry " /boot/grub2/grub.cfg | awk -F\' '{print "index=" NR+3 "\ntitle=\42" $2 "\42\nid=\42" $4 "\42"}'
index=0
title="Fedora Linux (6.0.12-300.fc37.x86_64) 37 (Server Edition)"
id="d6fxxxxxxxxxxxxxx-xxxxxxx-xxxxxxx-6.0.12-300.fc37.x86_64"
index=1
title="Fedora Linux (6.0.11-300.fc37.x86_64) 37 (Server Edition)"
id="d6xxxxxxxxxxxxxx-xxxxxxx-xxxxxxx-6.0.11-300.fc37.x86_64"
index=2
title="Fedora Linux (6.0.10-300.fc37.x86_64) 37 (Server Edition)"
id="d6fa414863684a5f9fef744668d30c9a-6.0.10-300.fc37.x86_64"
index=3
title="Fedora (0-rescue-d6fa414863684a5f9fef744668d30c9a) 32 (Thirty Two)"
id="d6xxxxxxxxxxxxxx-xxxxxxx-xxxxxxx-rescue"
index=4
title="Fedora Linux 37 (Server Edition) (on /dev/sda3)"
id="osprober-gnulinux-/boot/vmlinuz-6.0.11-300.fc37.x86_64--ecxxxxxxxxxxxxxx-xxxxxxx-xxxxxxx"
index=5
title="Fedora Linux 37 (Server Edition) (on /dev/sda3)"
id="osprober-gnulinux-/boot/vmlinuz-6.0.10-300.fc37.x86_64--ecxxxxxxxxxxxxxx-xxxxxxx-xxxxxxx"
index=6
title="Fedora Linux 37 (Server Edition) (on /dev/sda3)"
id="osprober-gnulinux-/boot/vmlinuz-6.0.10-200.fc36.x86_64--ecxxxxxxxxxxxxxx-xxxxxxx-xxxxxxx"
index=7
title="Fedora Linux 37 (Server Edition) (on /dev/sda3)"
id="osprober-gnulinux-/boot/vmlinuz-0-rescue-e8xxxxxxxxxxxxxx-xxxxxxx-xxxxxxxc"
index=8
title="Fedora Linux 35 (Server Edition) (on /dev/sde5)"
id="osprober-gnulinux-/boot/vmlinuz-5.17.5-200.fc35.x86_64--49xxxxxxxxxxxxxx-xxxxxxx-xxxxxxx"
index=9
title="Fedora Linux 35 (Server Edition) (on /dev/sde5)"
id="osprober-gnulinux-/boot/vmlinuz-5.17.4-200.fc35.x86_64--49xxxxxxxxxxxxxx-xxxxxxx-xxxxxxx"
index=10
title="Fedora Linux 35 (Server Edition) (on /dev/sde5)"
id="osprober-gnulinux-/boot/vmlinuz-5.16.20-200.fc35.x86_64--49xxxxxxxxxxxxxx-xxxxxxx-xxxxxxx"
index=11
title="Fedora Linux 35 (Server Edition) (on /dev/sde5)"
id="osprober-gnulinux-/boot/vmlinuz-5.14.17-301.fc35.x86_64--49xxxxxxxxxxxxxx-xxxxxxx-xxxxxxx"
index=12
title="Fedora Linux 35 (Server Edition) (on /dev/sde5)"
id="osprober-gnulinux-/boot/vmlinuz-5.14.16-301.fc35.x86_64--49xxxxxxxxxxxxxx-xxxxxxx-xxxxxxx"
index=13
title="Fedora Linux 35 (Server Edition) (on /dev/sde5)"
id="osprober-gnulinux-/boot/vmlinuz-5.14.16-201.fc34.x86_64--exxxxxxxxxxxxxx-xxxxxxx-xxxxxxx"
index=14
title="Fedora Linux 35 (Server Edition) (on /dev/sde5)"
id="osprober-gnulinux-/boot/vmlinuz-0-rescue-exxxxxxxxxxxxxx"
index=15
title="UEFI Firmware Settings"
id="uefi-firmware"

I have to try to use title also with grub2-set-default. And I have to check if dnf -y up when new kernel installed would update default index, or I have to do it manually then always.

Thanks for showing me your results.

Doesn’t look like ‘title’ is unique though as you have 7 entries all with the same title as above.

You might want to use ‘id’ as that seems to be (more) unique.

And yes, an update may change the index for a given Kernel and version. You just need to have a process that you should strictly follow each time you accept an updated Kernel. After all, you should know in advance if you are going to force or accept a Kernel update. Just run this script and change grub accordingly.

Ah, the joys of project management.

Glad this has been some help tho.