Grub: reboot to specific kernel

I’d like to ask for help getting grub-reboot to work.

The theory: According to this blog post (and other sources) I should be able to choose the kernel for the next reboot, using grub-reboot. However, this does not work for me; grub always boots to the default kernel.

Here’s what I tried:

$ grep GRUB_DEFAULT /etc/default/grub
GRUB_DEFAULT=saved
$ grep "menuentry " /boot/grub/grub.cfg 
menuentry 'Ubuntu' --class ubuntu --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-simple-f3a807d1-3fd6-4970-b741-5382e9801060' {
    menuentry 'Ubuntu, with Linux 4.4.0-43-generic' --class ubuntu --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-4.4.0-43-generic-advanced-f3a807d1-3fd6-4970-b741-5382e9801060' {
    menuentry 'Ubuntu, with Linux 4.4.0-43-generic (recovery mode)' --class ubuntu --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-4.4.0-43-generic-recovery-f3a807d1-3fd6-4970-b741-5382e9801060' {
    menuentry 'Ubuntu, with Linux 4.4.0-36-generic' --class ubuntu --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-4.4.0-36-generic-advanced-f3a807d1-3fd6-4970-b741-5382e9801060' {
    menuentry 'Ubuntu, with Linux 4.4.0-36-generic (recovery mode)' --class ubuntu --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-4.4.0-36-generic-recovery-f3a807d1-3fd6-4970-b741-5382e9801060' {

# Version 1, using the name
$ sudo grub-reboot "Ubuntu, with Linux 4.4.0-36-generic"

# Version 2, using the id
$ sudo grub-reboot gnulinux-4.4.0-36-generic-advanced-f3a807d1-3fd6-4970-b741-5382e9801060

# Version 3, counting
$ sudo grub-reboot 3

Neither of these commands seem to have an effect; after reboot, I always end up with the 4.4.0-43 kernel.

Note: This is on Ubuntu 16.04 Xenial. It is a server machine and I don’t have access to the console during boot, so I can’t look at the grub menu 🙁

Here is Solutions:

We have many solutions to this problem, But we recommend you to use the first solution because it is tested & true solution that will 100% work for you.

Solution 1

It seems the kernel you want to boot is in a submenu of grub (just look at the complete grub.cfg). man grub-reboot says:

Please note that menu items in submenus or sub-submenus require specifying the submenu components and then the menu item component. The
titles should be separated using the greater-than character (>) with no
extra spaces. Depending on your shell some characters including > may
need escaping. More information about this is available in the GRUB
Manual in the section about the ‘default’ command.

Maybe something like grub-reboot '2>2' will work for you.

Solution 2

Display Grub Menu Entries from Command Line

I created a script grub-menu.sh to make it easy to find the menu entry number:

Grub: reboot to specific kernel


Booting with Grub Menu Entry Number

If you wanted to reboot into Kernel 4.4.0-131 you would use:

sudo grub-reboot "1>6"

Getting the bash script grub-menu.sh

You can find the bash script in this Q&A: Display grub menu and options without rebooting?

Solution 3

I’ve been in a similar situation, and wanted a simple way to reboot into a different kernel or set the default. The menus that are generated in Ubuntu do make this less than trivial.

I’ve put together a script called boot-kernel that makes this easier. Its not perfect, but works well for at least official ubuntu kernels.

$ sudo ./boot-kernel --setup-only
changing GRUB_DEFAULT from 0 to "saved" in /etc/default/grub
apply change to /etc/default/grub
   --- /etc/default/grub    2018-01-12 19:40:38.681080878 +0000
   +++ /tmp/boot-kernel.GXbsRC  2018-01-12 19:40:50.525044373 +0000
   @@ -3,7 +3,7 @@
    # For full documentation of the options in this file, see:
    #   info -f grub -n 'Simple configuration'

   -GRUB_DEFAULT=0
   +GRUB_DEFAULT=saved
    GRUB_HIDDEN_TIMEOUT=0
    GRUB_HIDDEN_TIMEOUT_QUIET=true
    GRUB_TIMEOUT=0
execute: update-grub
Generating grub configuration file ...
Found linux image: /boot/vmlinuz-4.4.0-109-generic
Found initrd image: /boot/initrd.img-4.4.0-109-generic
Found linux image: /boot/vmlinuz-4.4.0-108-generic
Found initrd image: /boot/initrd.img-4.4.0-108-generic
done

$ sudo ./boot-kernel /boot/vmlinuz-4.4.0-108-generic
GRUB_DEFAULT already set to 'saved'. no change necessary.
selected /boot/vmlinuz-4.4.0-108-generic. entry: Advanced options for Ubuntu>Ubuntu, with Linux 4.4.0-108-generic
execute: grub-reboot "Advanced options for Ubuntu>Ubuntu, with Linux 4.4.0-108-generic"

Solution 4

The next tips will be usable in case if you have a standard grub menu. If you have two sub-menus you need to change your sub-menu number from 1 to the other number your sub-menu has and change -2 to the other value. For example, if you has Submenu 2 on the 3rd position, you need to change that numbers to 2 and maybe -3 in menunum variable setting.

Get list of kernels and output it:

    kernlist=$(grep -i "menuentry '" /boot/grub/grub.cfg|sed -r "s|--class .*$||g")
    printf "%s$kernlist\n"

Specifying kernel version we want to boot from:

    kernel=5.3.0-40-generic

Getting MENU_ENTRY number for our kernel if it is behind Advanced options for Ubuntu menu which has 1 MENU_ENTRY number:

    menuline=$($kernlist | grep -ne $kernel | grep -v recovery | cut -f1 -d":")
    menunum=$(($menuline-2))

Rebooting into desired kernel:

    sudo grub-reboot "1>$menunum" && reboot

One-line solution that requires kernel version correction but without reboot command:

kernel=5.3.0-40-generic; menuline=$(grep -i "menuentry '" /boot/grub/grub.cfg|sed -r "s|--class .*$||g" | grep -ne $kernel | grep -v recovery | cut -f1 -d":") && menunum=$(($menuline-2)) && sudo grub-reboot "1>$menunum"

Note: Use and implement solution 1 because this method fully tested our system.
Thank you 🙂

All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply