I think most distributions have moved additional kernels into the advanced options sub menu at this point, as TomTom found was the case with his
Arch.
I didn't want to alter my top level menu structure in order to select a previous kernel as the default. I found the answer here:
http://www.humans-enabled.com/2014/08/how-to-set-default-grub-kernel-boot.html
To summarize:
1) Find the $menuentry_id_option
for the submenu:
$ grep submenu /boot/grub/grub.cfg
submenu 'Advanced options for Debian GNU/Linux' $menuentry_id_option 'gnulinux-advanced-38ea4a12-6cfe-4ed9-a8b5-036295e62ffc' {
2) Find the $menuentry_id_option
for the menu entry for the kernel you want to use:
$ grep gnulinux /boot/grub/grub.cfg
menuentry 'Debian GNU/Linux' --class debian --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-simple-38ea4a12-6cfe-4ed9-a8b5-036295e62ffc' {
submenu 'Advanced options for Debian GNU/Linux' $menuentry_id_option 'gnulinux-advanced-38ea4a12-6cfe-4ed9-a8b5-036295e62ffc' {
menuentry 'Debian GNU/Linux, with Linux 4.18.0-0.bpo.1-rt-amd64' --class debian --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-4.18.0-0.bpo.1-rt-amd64-advanced-38ea4a12-6cfe-4ed9-a8b5-036295e62ffc' {
menuentry 'Debian GNU/Linux, with Linux 4.18.0-0.bpo.1-rt-amd64 (recovery mode)' --class debian --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-4.18.0-0.bpo.1-rt-amd64-recovery-38ea4a12-6cfe-4ed9-a8b5-036295e62ffc' {
menuentry 'Debian GNU/Linux, with Linux 4.18.0-0.bpo.1-amd64' --class debian --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-4.18.0-0.bpo.1-amd64-advanced-38ea4a12-6cfe-4ed9-a8b5-036295e62ffc' {
menuentry 'Debian GNU/Linux, with Linux 4.18.0-0.bpo.1-amd64 (recovery mode)' --class debian --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-4.18.0-0.bpo.1-amd64-recovery-38ea4a12-6cfe-4ed9-a8b5-036295e62ffc' {
menuentry 'Debian GNU/Linux, with Linux 4.17.0-0.bpo.1-amd64' --class debian --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-4.17.0-0.bpo.1-amd64-advanced-38ea4a12-6cfe-4ed9-a8b5-036295e62ffc' {
menuentry 'Debian GNU/Linux, with Linux 4.17.0-0.bpo.1-amd64 (recovery mode)' --class debian --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-4.17.0-0.bpo.1-amd64-recovery-38ea4a12-6cfe-4ed9-a8b5-036295e62ffc' {
menuentry 'Debian GNU/Linux, with Linux 4.9.0-8-amd64' --class debian --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-4.9.0-8-amd64-advanced-38ea4a12-6cfe-4ed9-a8b5-036295e62ffc' {
menuentry 'Debian GNU/Linux, with Linux 4.9.0-8-amd64 (recovery mode)' --class debian --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-4.9.0-8-amd64-recovery-38ea4a12-6cfe-4ed9-a8b5-036295e62ffc' {
3) Comment out your current default grub in /etc/default/grub
and replace it with the sub-menu's $menuentry_id_option
from step one, and the selected kernel's $menuentry_id_option
from step two separated by >
.
In my case the modified GRUB_DEFAULT
is:
#GRUB_DEFAULT=0
GRUB_DEFAULT="gnulinux-advanced-38ea4a12-6cfe-4ed9-a8b5-036295e62ffc>gnulinux-4.18.0-0.bpo.1-amd64-advanced-38ea4a12-6cfe-4ed9-a8b5-036295e62ffc"
4) Update grub to make the changes. For Debian this is done like so:
$ sudo update-grub
Done. Now when you boot, the advanced menu should have an asterisk and you should boot into the selected kernel. You can confirm this with uname
.
$ uname -a
Linux NAME 4.18.0-0.bpo.1-amd64 #1 SMP Debian 4.18.0-0 (2018-09-13) x86_64 GNU/Linux
Changing this back to the most recent kernel is as simple as commenting out the new line and uncommenting #GRUB_DEFAULT=0
:
GRUB_DEFAULT=0
#GRUB_DEFAULT="gnulinux-advanced-38ea4a12-6cfe-4ed9-a8b5-036295e62ffc>gnulinux-4.18.0-0.bpo.1-amd64-advanced-38ea4a12-6cfe-4ed9-a8b5-036295e62ffc"
then rerunning update-grub
.
Do this lines exist in the your /etc/default/grub
? If not, add them.
GRUB_TIMEOUT=10
GRUB_TIMEOUT_STYLE=menu
run update-grub
afterwards to update /boot/grub/grub.cfg
You can check, if the needed changes has happened, by this way:
grep -i timeout /boot/grub/grub.cfg
Output should be contained such values:
set timeout_style=menu
set timeout=10
From the grub manual:
GRUB_TIMEOUT
Boot the default entry this many seconds after the menu is displayed,
unless a key is pressed. The default is 5. Set to 0 to boot
immediately without displaying the menu, or to -1 to wait
indefinitely. If GRUB_TIMEOUT_STYLE is set to countdown or
hidden, the timeout is instead counted before the menu is displayed.
GRUB_TIMEOUT_STYLE
If this option is unset or set to menu, then GRUB will display the
menu and then wait for the timeout set by GRUB_TIMEOUT to expire
before booting the default entry. Pressing a key interrupts the
timeout. If this option is set to countdown or hidden, then,
before displaying the menu, GRUB will wait for the timeout set by
GRUB_TIMEOUT to expire. If ESC is pressed during that time, it will display the menu and wait for input. If a hotkey associated with
a menu entry is pressed, it will boot the associated menu entry
immediately. If the timeout expires before either of these happens, it
will boot the default entry. In the countdown case, it will show a
one-line indication of the remaining time.
Best Answer
See this bug: https://bugs.archlinux.org/task/16702#comment80122
And this blogpost: http://losinggeneration.homelinux.org/2009/10/16/why-arch-linuxs-kernel-upgrades-suck/
So far I haven't found a good solution, but I will update if I do.
One thing to keep in mind beyond grub, the kernel, and initrd is /usr/lib/modules/. When the linux package updates the old package deletes it's folders in /usr/lib/modules/ and the new kernel adds its new modules. If you want both kernels working, you're going to want both sets of modules. And /usr/src/ contains the kernel headers (needed to build new modules, such as the nvidia drivers), so you'll probably want to keep those, too.
The steps I guess would be something like:
1. Detect linux package is going to be upgraded.
2. Backup what it's going to delete on uninstall (/usr/src/$(uname -r), /usr/lib/modules/$(uname -r), /boot/{vmlinuz-linux,initramfs-linux.img,initramfs-linux-fallback.img})
3. Let pacman do its upgrade
4. Restore everything in 2 (probably giving a new name to the stuff in /boot
5. Edit grub or whatever.
Alternate steps (somewhat less good)
1. Let pacman update
2. Detect kernel was updated
3. from /var/cache/packman/pkg/linux-${previous_version}-pkg.tar.xz extract /usr/src/, /usr/lib/{modules,extramodules}, and /boot/vmlinuz (renaming the one in /boot, obviously)
4. run mkinitcpio with the -k option to build the old init
5. Edit grub or whatever
In this alternate method, you loose your 3rd party modules (virtual box, ATI/Nvidia, etc), but it might be something you could run from cron and automagically detect kernel updates have occured.