DNF Upgrade empties GRUB menu

I recently posted about this and found a temporary solution. My problem now is every time I upgrade my system either with GUI or dnf upgrade I need to boot using grub terminal into the rescue kernel and re-generate my grub menu. How can I make this fix hold permanently?

Do you have the os-prober package installed? I believe it should be if you are dual-booting.

Ideally, from your original post, you shouldn’t need to disable BLS like you did, since the entries don’t appear in grub.cfg when BLS is enabled, they are found under /boot/loader/entries.

I do have os-prober, should I re-enable BLS?

If it was me, I would keep it as the OS intended, which is BLS enabled. Then once it’s re-enabled check the files in the directory /boot/loader/entries and you’ll see everything inside these relating to booting your systems.

Once you’ve removed the entry that you added to disable BLS, then run the command below:

grub2-mkconfig --update-bls-cmdline -o /boot/grub2/grub.cfg

it may or may not fix your problem, but at least you will be the default system configuration which pretty much everyone will be using so makes it easier to fix in the future than diverging by disabling it.

1 Like

Thanks for the suggestion, but --update-bls-cmdline is not an option on grub2-mkconfig for me. Is this a Rocky 9 option? I am on 8.10.

Ah yeah, it is most likely an EL9 thing, so yeah you can use the command without that part. So:

grub2-mkconfig -o /boot/grub2/grub.cfg

no need to set the BLS entry to true in the config file that you added to, just completely remove the line.

@Moksh has not confirmed whether the system boots with UEFI or with legacy mode.
On Rocky 8 that determines the proper location of the grub.cfg


In principle, remove/install of a kernel should merely modify related entry (whether BLS file or lines in grub.cfg) and not erase all existing entries. Furthermore, package transactions that do not include kernel packages should not affect entries at all.

The system boots UEFI

In that case:

grub2-mkconfig -o /boot/efi/EFI/rocky/grub.cfg

The UEFI (presumably) loads /boot/efi/EFI/rocky/grubx64.efi
which in turn reads /boot/efi/EFI/rocky/grub.cfg

Since the /boot/efi/EFI/rocky/grub.cfg in Rocky 8 is not a
“stub that includes /boot/grub2/grub.cfg”, nothing reads the /boot/grub2/grub.cfg.

1 Like

@jlehtone command for grub is correct, mine was from EL9. So use his to generate it. You can also find out by looking under /etc/ and there will be symlinks to the particular grub file that he mentioned. Either grub2-efi.cfg or grub2.cfg depending on whether UEFI or BIOSBOOT is used.

Thanks for the command @jlehtone but the main issue I’m having is not necessarily in running that command it is that when I update the grub menu empties. Maybe I’m not understanding what you’re asking me to do.

I do have grub2.cfg

[moksh@resolve etc]$ ls -l ./grub2.cfg 
lrwxrwxrwx. 1 root root 22 Apr  8 08:13 ./grub2.cfg -> ../boot/grub2/grub.cfg

There should be two symlinks:

# symlinks -v /etc | grep grub
other_fs: /etc/grub2-efi.cfg -> ../boot/efi/EFI/almalinux/grub.cfg
dangling: /etc/grub2.cfg -> ../boot/grub2/grub.cfg

Note how one of the links is dangling – my system does not have file /boot/grub2/grub.cfg
That is by design; only one of the links should be valid on el8 system.


The first question is, does that command ensure that there are entries for each installed kernel?
Did you check (without reboot) after running the grub2-mkconfig that there are expected files with expected content?

Did you check before&after dnf up which files were modified/added/removed?
ls -ltr /boot /boot/grub2 /boot/efi/EFI/rocky /boot/loader/entries

For Rocky9 or other EL9’s this is true, however for EL8 or Rocky 8 there is either one or the other:

[root@rocky8 etc]# ls -lha | grep grub
lrwxrwxrwx.  1 root root     30 Apr  8 17:13 grub2-efi.cfg -> ../boot/efi/EFI/rocky/grub.cfg
drwx------.  2 root root   4.0K Apr 11 09:48 grub.d

so depending on how system was installed with BIOS or UEFI, you get either the symlink to EFI or BIOS grub config. That said, I could probably install grub2-pc package and get the symlink to the other one.

yes it would be good to see the output of this command. It would even be nicer to see the contents of grub2.cfg posted because as already explained, some stuff appears in grub2.cfg and the remainder under /boot/loader/entries.

On AlmaLinux 8 the ‘grub2-pc’ is required by kernel-core and therefore always installed (even on UEFI system). Rocky seems smarter on this detail.

Before running dnf upgrade

[moksh@resolve ~]$ symlinks -v /etc | grep grub
dangling: /etc/grub2.cfg -> ../boot/grub2/grub.cfg

[moksh@resolve ~]$ cd /etc
[moksh@resolve etc]$ ls -lha | grep grub
lrwxrwxrwx.   1 root root      22 Apr  8 08:13 grub2.cfg -> ../boot/grub2/grub.cfg
-rw-------.   1 root root    7.1K Apr  7 19:47 grub.cfg
drwx------.   2 root root    4.0K Apr 14 00:10 grub.d

[moksh@resolve etc]$ sudo ls -ltr /boot /boot/grub2 /boot/efi/EFI/rocky /boot/loader/entries
/boot:
total 476688
drwxr-xr-x. 3 root root        17 Mar  4 11:42 efi
drwxr-xr-x. 3 root root        21 Mar  4 11:43 loader
-rwxr-xr-x. 1 root root  10881352 Mar  4 11:45 vmlinuz-0-rescue-82a24f939aa14e6da0b496ef749bc8bd
-rw-------. 1 root root 131214050 Mar  4 11:45 initramfs-0-rescue-82a24f939aa14e6da0b496ef749bc8bd.img
-rw-------. 1 root root  52546535 Mar  4 12:32 initramfs-4.18.0-553.40.1.el8_10.x86_64.img.backup
-rw-------. 1 root root   4510017 Mar 10 04:43 System.map-4.18.0-553.44.1.el8_10.x86_64
-rw-r--r--. 1 root root    202338 Mar 10 04:43 config-4.18.0-553.44.1.el8_10.x86_64
-rwxr-xr-x. 1 root root  10881352 Mar 10 04:43 vmlinuz-4.18.0-553.44.1.el8_10.x86_64
-rw-------. 1 root root   4510017 Mar 19 11:39 System.map-4.18.0-553.45.1.el8_10.x86_64
-rw-r--r--. 1 root root    202338 Mar 19 11:39 config-4.18.0-553.45.1.el8_10.x86_64
-rwxr-xr-x. 1 root root  10881352 Mar 19 11:40 vmlinuz-4.18.0-553.45.1.el8_10.x86_64
lrwxrwxrwx. 1 root root        53 Mar 20 13:38 symvers-4.18.0-553.44.1.el8_10.x86_64.gz -> /lib/modules/4.18.0-553.44.1.el8_10.x86_64/symvers.gz
-rw-------. 1 root root  52551675 Mar 20 13:40 initramfs-4.18.0-553.44.1.el8_10.x86_64.img
-rw-------. 1 root root  29031936 Mar 21 00:02 initramfs-4.18.0-553.44.1.el8_10.x86_64kdump.img
lrwxrwxrwx. 1 root root        53 Mar 23 10:27 symvers-4.18.0-553.45.1.el8_10.x86_64.gz -> /lib/modules/4.18.0-553.45.1.el8_10.x86_64/symvers.gz
-rw-------. 1 root root  29150720 Mar 24 22:43 initramfs-4.18.0-553.45.1.el8_10.x86_64kdump.img
-rw-------. 1 root root  52548873 Mar 26 00:37 initramfs-4.18.0-553.45.1.el8_10.x86_64.img
-rw-------. 1 root root   4510017 Apr  3 07:38 System.map-4.18.0-553.47.1.el8_10.x86_64
-rw-r--r--. 1 root root    202338 Apr  3 07:38 config-4.18.0-553.47.1.el8_10.x86_64
-rwxr-xr-x. 1 root root  10881352 Apr  3 07:38 vmlinuz-4.18.0-553.47.1.el8_10.x86_64
lrwxrwxrwx. 1 root root        53 Apr  7 19:53 symvers-4.18.0-553.47.1.el8_10.x86_64.gz -> /lib/modules/4.18.0-553.47.1.el8_10.x86_64/symvers.gz
-rw-------. 1 root root  54234120 Apr  7 19:55 initramfs-4.18.0-553.47.1.el8_10.x86_64.img
-rw-------. 1 root root  29154816 Apr  7 21:24 initramfs-4.18.0-553.47.1.el8_10.x86_64kdump.img
drwx------. 4 root root       107 Apr 17 23:02 grub2

/boot/loader/entries:
total 16
-rw-r--r--. 1 root root 346 Mar 10 04:43 82a24f939aa14e6da0b496ef749bc8bd-4.18.0-553.44.1.el8_10.x86_64.conf
-rw-r--r--. 1 root root 346 Mar 19 11:40 82a24f939aa14e6da0b496ef749bc8bd-4.18.0-553.45.1.el8_10.x86_64.conf
-rw-r--r--. 1 root root 346 Apr  3 07:38 82a24f939aa14e6da0b496ef749bc8bd-4.18.0-553.47.1.el8_10.x86_64.conf
-rw-r--r--. 1 root root 393 Apr 14 00:10 82a24f939aa14e6da0b496ef749bc8bd-0-rescue.conf

/boot/efi/EFI/rocky:
total 12
-rw-------. 1 root root 8962 Apr 14 00:16 grub.cfg

/boot/grub2:
total 44
-rw-r--r--. 1 root root   68 Mar  4 11:46 device.map
drwxr-xr-x. 2 root root   25 Mar  4 11:46 fonts
drwxr-xr-x. 2 root root 8192 Mar  4 11:46 i386-pc
-rw-------. 1 root root 8962 Apr  7 21:23 grub.cfg.rpmsave
-rw-------. 1 root root 8962 Apr 14 00:16 grub.cfg
-rw-------. 1 root root 1024 Apr 17 23:02 grubenv

After running dnf upgrade

[moksh@resolve etc]$ symlinks -v /etc | grep grub
dangling: /etc/grub2.cfg -> ../boot/grub2/grub.cfg

[moksh@resolve etc]$ ls -lha | grep grub
lrwxrwxrwx.   1 root root      22 Apr  8 08:13 grub2.cfg -> ../boot/grub2/grub.cfg
-rw-------.   1 root root    7.1K Apr  7 19:47 grub.cfg
drwx------.   2 root root    4.0K Apr 14 00:10 grub.d


[moksh@resolve etc]$ sudo ls -ltr /boot /boot/grub2 /boot/efi/EFI/rocky /boot/loader/entries
/boot/efi/EFI/rocky:
total 12
-rw-------. 1 root root 8962 Apr 14 00:16 grub.cfg

/boot/grub2:
total 40
-rw-r--r--. 1 root root   68 Mar  4 11:46 device.map
drwxr-xr-x. 2 root root   25 Mar  4 11:46 fonts
drwxr-xr-x. 2 root root 8192 Mar  4 11:46 i386-pc
-rw-------. 1 root root 8962 Apr  7 21:23 grub.cfg.rpmsave
-rw-------. 1 root root 1024 Apr 17 23:07 grubenv
-rw-------. 1 root root 7170 Apr 17 23:07 grub.cfg

/boot:
total 448332
drwxr-xr-x. 3 root root        17 Mar  4 11:42 efi
drwxr-xr-x. 3 root root        21 Mar  4 11:43 loader
-rwxr-xr-x. 1 root root  10881352 Mar  4 11:45 vmlinuz-0-rescue-82a24f939aa14e6da0b496ef749bc8bd
-rw-------. 1 root root 131214050 Mar  4 11:45 initramfs-0-rescue-82a24f939aa14e6da0b496ef749bc8bd.img
-rw-------. 1 root root  52546535 Mar  4 12:32 initramfs-4.18.0-553.40.1.el8_10.x86_64.img.backup
-rw-------. 1 root root   4510017 Mar 19 11:39 System.map-4.18.0-553.45.1.el8_10.x86_64
-rw-r--r--. 1 root root    202338 Mar 19 11:39 config-4.18.0-553.45.1.el8_10.x86_64
-rwxr-xr-x. 1 root root  10881352 Mar 19 11:40 vmlinuz-4.18.0-553.45.1.el8_10.x86_64
lrwxrwxrwx. 1 root root        53 Mar 23 10:27 symvers-4.18.0-553.45.1.el8_10.x86_64.gz -> /lib/modules/4.18.0-553.45.1.el8_10.x86_64/symvers.gz
-rw-------. 1 root root  29150720 Mar 24 22:43 initramfs-4.18.0-553.45.1.el8_10.x86_64kdump.img
-rw-------. 1 root root  52548873 Mar 26 00:37 initramfs-4.18.0-553.45.1.el8_10.x86_64.img
-rw-------. 1 root root   4510017 Apr  3 07:38 System.map-4.18.0-553.47.1.el8_10.x86_64
-rw-r--r--. 1 root root    202338 Apr  3 07:38 config-4.18.0-553.47.1.el8_10.x86_64
-rwxr-xr-x. 1 root root  10881352 Apr  3 07:38 vmlinuz-4.18.0-553.47.1.el8_10.x86_64
lrwxrwxrwx. 1 root root        53 Apr  7 19:53 symvers-4.18.0-553.47.1.el8_10.x86_64.gz -> /lib/modules/4.18.0-553.47.1.el8_10.x86_64/symvers.gz
-rw-------. 1 root root  54234120 Apr  7 19:55 initramfs-4.18.0-553.47.1.el8_10.x86_64.img
-rw-------. 1 root root  29154816 Apr  7 21:24 initramfs-4.18.0-553.47.1.el8_10.x86_64kdump.img
-rw-------. 1 root root   4507711 Apr 16 04:47 System.map-4.18.0-553.50.1.el8_10.x86_64
-rw-r--r--. 1 root root    202338 Apr 16 04:47 config-4.18.0-553.50.1.el8_10.x86_64
-rwxr-xr-x. 1 root root  10881352 Apr 16 04:47 vmlinuz-4.18.0-553.50.1.el8_10.x86_64
drwx------. 4 root root       107 Apr 17 23:02 grub2
lrwxrwxrwx. 1 root root        53 Apr 17 23:10 symvers-4.18.0-553.50.1.el8_10.x86_64.gz -> /lib/modules/4.18.0-553.50.1.el8_10.x86_64/symvers.gz
-rw-------. 1 root root  52551349 Apr 17 23:12 initramfs-4.18.0-553.50.1.el8_10.x86_64.img

/boot/loader/entries:
total 16
-rw-r--r--. 1 root root 421 Apr 17 23:07 82a24f939aa14e6da0b496ef749bc8bd-0-rescue.conf
-rw-r--r--. 1 root root 402 Apr 17 23:12 82a24f939aa14e6da0b496ef749bc8bd-4.18.0-553.45.1.el8_10.x86_64.conf
-rw-r--r--. 1 root root 402 Apr 17 23:12 82a24f939aa14e6da0b496ef749bc8bd-4.18.0-553.47.1.el8_10.x86_64.conf
-rw-r--r--. 1 root root 374 Apr 17 23:12 82a24f939aa14e6da0b496ef749bc8bd-4.18.0-553.50.1.el8_10.x86_64.conf

Following the last post I also ran the below!

[moksh@resolve etc]$ sudo grub2-mkconfig -o /boot/efi/EFI/rocky/grub.cfg
Generating grub configuration file ...
Found Windows 10 on /dev/nvme1n1p1
done
[moksh@resolve etc]$ sudo cat /etc/grub2.cfg 
#
# DO NOT EDIT THIS FILE
#
# It is automatically generated by grub2-mkconfig using templates
# from /etc/grub.d and settings from /etc/default/grub
#

### BEGIN /etc/grub.d/00_header ###
set pager=1

if [ -f ${config_directory}/grubenv ]; then
  load_env -f ${config_directory}/grubenv
elif [ -s $prefix/grubenv ]; then
  load_env
fi
if [ "${next_entry}" ] ; then
   set default="${next_entry}"
   set next_entry=
   save_env next_entry
   set boot_once=true
else
   set default="${saved_entry}"
fi

if [ x"${feature_menuentry_id}" = xy ]; then
  menuentry_id_option="--id"
else
  menuentry_id_option=""
fi

export menuentry_id_option

if [ "${prev_saved_entry}" ]; then
  set saved_entry="${prev_saved_entry}"
  save_env saved_entry
  set prev_saved_entry=
  save_env prev_saved_entry
  set boot_once=true
fi

function savedefault {
  if [ -z "${boot_once}" ]; then
    saved_entry="${chosen}"
    save_env saved_entry
  fi
}

function load_video {
  if [ x$feature_all_video_module = xy ]; then
    insmod all_video
  else
    insmod efi_gop
    insmod efi_uga
    insmod ieee1275_fb
    insmod vbe
    insmod vga
    insmod video_bochs
    insmod video_cirrus
  fi
}

terminal_output console
if [ x$feature_timeout_style = xy ] ; then
  set timeout_style=menu
  set timeout=5
# Fallback normal timeout code in case the timeout_style feature is
# unavailable.
else
  set timeout=5
fi
### END /etc/grub.d/00_header ###

### BEGIN /etc/grub.d/00_tuned ###
set tuned_params=""
set tuned_initrd=""
### END /etc/grub.d/00_tuned ###

### BEGIN /etc/grub.d/01_users ###
if [ -f ${prefix}/user.cfg ]; then
  source ${prefix}/user.cfg
  if [ -n "${GRUB2_PASSWORD}" ]; then
    set superusers="root"
    export superusers
    password_pbkdf2 root ${GRUB2_PASSWORD}
  fi
fi
### END /etc/grub.d/01_users ###

### BEGIN /etc/grub.d/08_fallback_counting ###
insmod increment
# Check if boot_counter exists and boot_success=0 to activate this behaviour.
if [ -n "${boot_counter}" -a "${boot_success}" = "0" ]; then
  # if countdown has ended, choose to boot rollback deployment,
  # i.e. default=1 on OSTree-based systems.
  if  [ "${boot_counter}" = "0" -o "${boot_counter}" = "-1" ]; then
    set default=1
    set boot_counter=-1
  # otherwise decrement boot_counter
  else
    decrement boot_counter
  fi
  save_env boot_counter
fi
### END /etc/grub.d/08_fallback_counting ###

### BEGIN /etc/grub.d/10_linux ###
insmod part_msdos
insmod xfs
if [ x$feature_platform_search_hint = xy ]; then
  search --no-floppy --fs-uuid --set=root  e56ad71c-f8a1-4b6c-be5b-9b43a1cab359
else
  search --no-floppy --fs-uuid --set=root e56ad71c-f8a1-4b6c-be5b-9b43a1cab359
fi
insmod part_msdos
insmod xfs
if [ x$feature_platform_search_hint = xy ]; then
  search --no-floppy --fs-uuid --set=boot  e56ad71c-f8a1-4b6c-be5b-9b43a1cab359
else
  search --no-floppy --fs-uuid --set=boot e56ad71c-f8a1-4b6c-be5b-9b43a1cab359
fi

# This section was generated by a script. Do not modify the generated file - all changes
# will be lost the next time file is regenerated. Instead edit the BootLoaderSpec files.
#
# The blscfg command parses the BootLoaderSpec files stored in /boot/loader/entries and
# populates the boot menu. Please refer to the Boot Loader Specification documentation
# for the files format: https://www.freedesktop.org/wiki/Specifications/BootLoaderSpec/.

# The kernelopts variable should be defined in the grubenv file. But to ensure that menu
# entries populated from BootLoaderSpec files that use this variable work correctly even
# without a grubenv file, define a fallback kernelopts variable if this has not been set.
#
# The kernelopts variable in the grubenv file can be modified using the grubby tool or by
# executing the grub2-mkconfig tool. For the latter, the values of the GRUB_CMDLINE_LINUX
# and GRUB_CMDLINE_LINUX_DEFAULT options from /etc/default/grub file are used to set both
# the kernelopts variable in the grubenv file and the fallback kernelopts variable.
if [ -z "${kernelopts}" ]; then
  set kernelopts="root=/dev/mapper/rl_resolve-root ro crashkernel=auto resume=/dev/mapper/rl_resolve-swap rd.lvm.lv=rl_resolve/root rd.lvm.lv=rl_resolve/swap rhgb quiet nouveau.modset=0 rd.driver.blacklist=nouveau "
fi

insmod blscfg
blscfg
### END /etc/grub.d/10_linux ###

### BEGIN /etc/grub.d/10_reset_boot_success ###
# Hiding the menu is ok if last boot was ok or if this is a first boot attempt to boot the entry
if [ "${boot_success}" = "1" -o "${boot_indeterminate}" = "1" ]; then
  set menu_hide_ok=1
else
  set menu_hide_ok=0 
fi
# Reset boot_indeterminate after a successful boot
if [ "${boot_success}" = "1" ] ; then
  set boot_indeterminate=0
# Avoid boot_indeterminate causing the menu to be hidden more then once
elif [ "${boot_indeterminate}" = "1" ]; then
  set boot_indeterminate=2
fi
# Reset boot_success for current boot 
set boot_success=0
save_env boot_success boot_indeterminate
### END /etc/grub.d/10_reset_boot_success ###

### BEGIN /etc/grub.d/12_menu_auto_hide ###
if [ x$feature_timeout_style = xy ] ; then
  if [ "${menu_show_once}" ]; then
    unset menu_show_once
    save_env menu_show_once
    set timeout_style=menu
    set timeout=60
  elif [ "${menu_auto_hide}" -a "${menu_hide_ok}" = "1" ]; then
    set orig_timeout_style=${timeout_style}
    set orig_timeout=${timeout}
    if [ "${fastboot}" = "1" ]; then
      # timeout_style=menu + timeout=0 avoids the countdown code keypress check
      set timeout_style=menu
      set timeout=0
    else
      set timeout_style=hidden
      set timeout=1
    fi
  fi
fi
### END /etc/grub.d/12_menu_auto_hide ###

### BEGIN /etc/grub.d/20_linux_xen ###
### END /etc/grub.d/20_linux_xen ###

### BEGIN /etc/grub.d/20_ppc_terminfo ###
### END /etc/grub.d/20_ppc_terminfo ###

### BEGIN /etc/grub.d/30_os-prober ###
menuentry 'Windows 10 (on /dev/nvme1n1p1)' --class windows --class os $menuentry_id_option 'osprober-chain-3AA29E76A29E367B' {
	savedefault
	insmod part_msdos
	insmod ntfs
	set root='hd0,msdos1'
	if [ x$feature_platform_search_hint = xy ]; then
	  search --no-floppy --fs-uuid --set=root --hint='hd0,msdos1'  3AA29E76A29E367B
	else
	  search --no-floppy --fs-uuid --set=root 3AA29E76A29E367B
	fi
	parttool ${root} hidden-
	drivemap -s (hd0) ${root}
	chainloader +1
}
# Other OS found, undo autohiding of menu unless menu_auto_hide=2
if [ "${orig_timeout_style}" -a "${menu_auto_hide}" != "2" ]; then
  set timeout_style=${orig_timeout_style}
  set timeout=${orig_timeout}
fi
### END /etc/grub.d/30_os-prober ###

### BEGIN /etc/grub.d/30_uefi-firmware ###
### END /etc/grub.d/30_uefi-firmware ###

### BEGIN /etc/grub.d/35_fwupd ###
### END /etc/grub.d/35_fwupd ###

### BEGIN /etc/grub.d/40_custom ###
# This file provides an easy way to add custom menu entries.  Simply type the
# menu entries you want to add after this comment.  Be careful not to change
# the 'exec tail' line above.
### END /etc/grub.d/40_custom ###

### BEGIN /etc/grub.d/41_custom ###
if [ -f  ${config_directory}/custom.cfg ]; then
  source ${config_directory}/custom.cfg
elif [ -z "${config_directory}" -a -f  $prefix/custom.cfg ]; then
  source $prefix/custom.cfg;
fi
### END /etc/grub.d/41_custom ###