Startup and Boot FailuresLesson 2 of 4
GRUB, boot entries and kernel arguments
Edit kernel arguments for one boot, make them permanent with grubby, and rebuild a missing or broken boot configuration.
grubbygrubby --info=ALLgrubby --update-kernelgrubby --set-defaultgrub2-mkconfiggrub2-editenv/etc/default/grub/boot/loader/entries/proc/cmdlinednf reinstallkernel-install
After this lesson you can
- Edit the kernel command line for a single boot from the GRUB menu.
- Add, remove and verify permanent kernel arguments, and choose the default entry, with grubby.
- Rebuild grub.cfg and restore a missing boot entry or kernel from a running or rescue system.
The idea
GRUB 2 starts the kernel. On RHEL it needs three things: its own files, a list of boot entries, and a place to remember the default. How those are kept has changed over the years, and mixing old and new habits is the usual source of trouble.
Where the pieces are
| Item | Location | Notes |
|---|---|---|
| Boot loader (UEFI) | /boot/efi/EFI/redhat/ | shimx64.efi, grubx64.efi, grub.cfg (a short stub on UEFI) |
| Boot loader (BIOS) | In the MBR/BIOS-boot partition, files in /boot/grub2/ | grub.cfg here is the real configuration |
| Boot entries | /boot/loader/entries/*.conf | BLS (Boot Loader Specification): one file per kernel, with title, linux, initrd, options |
| Default entry | /boot/grub2/grubenv (saved_entry) | Edited by grub2-editenv or grubby --set-default |
| Settings | /etc/default/grub | Defaults used when regenerating; GRUB_CMDLINE_LINUX is the shared kernel argument line |
| Kernels | /boot/vmlinuz-*, /boot/initramfs-*.img | Installed by the kernel-core package; /boot is often its own partition |
A BLS entry looks like this:
title Red Hat Enterprise Linux (6.12.0-55.el10.x86_64) 10.2
version 6.12.0-55.el10.x86_64
linux /vmlinuz-6.12.0-55.el10.x86_64
initrd /initramfs-6.12.0-55.el10.x86_64.img $tuned_initrd
options root=/dev/mapper/rhel-root ro crashkernel=1G-4G:192M rd.lvm.lv=rhel/root rhgb quiet $tuned_params
grub_users $grub_users
grub_arg --unrestricted
grub_class rhel
The options line is the kernel command line. grubby edits this file; grub2-mkconfig does not need to be run for a normal argument change on a current RHEL.
/etc/default/grub versus grubby
GRUB_CMDLINE_LINUXin/etc/default/grubis the argument line used when new kernels are installed. Changing it and runninggrub2-mkconfigdoes not alter existing entries on a BLS system.grubby --update-kernel=ALL --args=...changes the entries that already exist. To affect future kernels as well, update both: grubby for what exists now,/etc/default/grubfor what will be installed.
What the GRUB prompts mean
| You see | Meaning | First action |
|---|---|---|
| Menu, then kernel loads normally | Fine | |
| Menu has no entry for the kernel you need | Entry file missing or /boot not readable | Boot another entry, or rescue; then kernel-install add |
grub> | grub.cfg not found or unreadable | ls, ls (hd0,gpt2)/ to find the files; configfile or boot manually |
grub rescue> | GRUB lost even its modules | Boot rescue media, chroot, reinstall (below) |
error: unknown filesystem | /boot file system damaged or driver missing | Rescue, xfs_repair/e2fsck on /boot |
Try it
For one boot: edit the entry in the menu
At the GRUB menu press e on the entry. Find the line that starts with linux, move to its end, and add the argument. Ctrl+x boots with it; Esc abandons the edit. Nothing is saved.
Common one-boot arguments:
| Add | Effect |
|---|---|
systemd.unit=rescue.target | Boot to rescue mode |
systemd.unit=emergency.target | Boot to emergency mode |
rd.break | Stop in the initramfs before the switch to the real root |
enforcing=0 | SELinux permissive for this boot (diagnosis only) |
init=/bin/bash | Start a shell instead of systemd (read-only root, no services) |
systemd.mask=foo.service | Do not start one unit |
Remove rhgb quiet | Show boot messages |
Permanently: grubby
sudo grubby --info=DEFAULT
index=0
kernel="/boot/vmlinuz-6.12.0-55.el10.x86_64"
args="ro crashkernel=1G-4G:192M,4G-64G:256M,64G-:512M rd.lvm.lv=rhel/root rhgb quiet"
root="/dev/mapper/rhel-root"
initrd="/boot/initramfs-6.12.0-55.el10.x86_64.img"
title="Red Hat Enterprise Linux (6.12.0-55.el10.x86_64) 10.2"
id="6fa8...-6.12.0-55.el10.x86_64"
sudo grubby --update-kernel=ALL --args="audit=1" --remove-args="rhgb quiet"
sudo grubby --info=ALL | grep ^args
sudo grubby --default-kernel
sudo grubby --set-default /boot/vmlinuz-6.12.0-55.el10.x86_64
--update-kernel accepts ALL, DEFAULT or a path. --args adds or changes, --remove-args removes. After a reboot, confirm in /proc/cmdline, because that is what the kernel actually received, not what the file says.
Rebuilding the configuration
sudo grub2-mkconfig -o /boot/grub2/grub.cfg
On UEFI systems RHEL’s grub.cfg in /boot/efi/EFI/redhat/ is a stub that loads /boot/grub2/grub.cfg, so the command above is correct on both firmware types on current releases; if the output path is wrong for your layout, the man page grub2-mkconfig(8) and the existing grub.cfg stub show it.
Bringing back a boot entry or the boot loader
From a running system, or from rescue media after you mount the installed system and chroot into it:
# entries
sudo kernel-install add $(uname -r) /lib/modules/$(uname -r)/vmlinuz
# missing kernel or initramfs files
sudo dnf reinstall kernel-core
sudo dracut -f --kver $(uname -r)
# damaged UEFI boot files
sudo dnf reinstall shim-x64 grub2-efi-x64
sudo grub2-mkconfig -o /boot/grub2/grub.cfg
On UEFI you do not run grub2-install on RHEL; reinstalling the shim and grub2-efi packages restores the files in the EFI system partition. If the firmware no longer lists the entry, efibootmgr -v shows the boot variables and efibootmgr -c recreates one. On BIOS systems grub2-install /dev/sda rewrites the loader to the disk.
The rescue steps, in order, when the installed system will not start:
- Boot the installation media, choose Troubleshooting → Rescue a Red Hat Enterprise Linux system.
- Let it find the installation (
1Continue mounts it at/mnt/sysroot, read-write). chroot /mnt/sysroot, repair,exit,reboot.- If you changed files in a SELinux enforcing system, run
touch /.autorelabelbefore rebooting.
When the boot loader is the problem
| Symptom | Cause | Fix |
|---|---|---|
| Menu has old kernels only | New kernel’s entry missing | kernel-install add or reinstall kernel-core |
New argument not in /proc/cmdline | Edited /etc/default/grub only | grubby --update-kernel=ALL --args=... |
| Argument present after update, but gone after a new kernel installs | Only the entries were changed | Update GRUB_CMDLINE_LINUX as well |
| Wrong kernel boots by default | saved_entry points elsewhere | grubby --set-default |
grub> prompt | grub.cfg unreachable | ls/configfile to boot once, then repair |
| Kernel loads, then “Unable to mount root” | Wrong root= or missing driver | Compare root= with lsblk; rebuild initramfs |
| Boot fails only with Secure Boot on | Unsigned module or loader | Use the signed packages; do not copy loaders by hand |
Going further
Protecting the menu. Editing the menu with e is the reason the physical console must be trusted. A GRUB password (grub2-setpassword) requires it for edits while still allowing the default boot. Beyond the exam: UEFI boot variables, signed kernels with Secure Boot, and the Unified Kernel Image format are all moving how boot is configured; RHEL 10 still uses the model above.
Practice
0 of 3 done
Do these on your own system. They get harder. Check each result, then tick it off.
- Warm-up
One boot only
Reboot and, from the GRUB menu, boot the default kernel into rescue mode for this boot only, without changing any file. After login, prove the change is temporary: show the argument in
/proc/cmdline, then reboot normally and show it is gone.Check your result
- In the rescue boot,
grep -o 'systemd.unit=rescue.target' /proc/cmdlineprints the argument andsystemctl get-defaultstill printsmulti-user.targetorgraphical.target. - After a normal reboot, the same
grepprints nothing.
Hint
In the GRUB menu press
e, go to the line starting withlinux, pressEnd, appendsystemd.unit=rescue.target, thenCtrl+xto boot. The edit exists only in memory.Solution
GRUB menu: e -> cursor to the end of the "linux" line -> add: systemd.unit=rescue.target -> Ctrl+xgrep -o 'systemd.unit=[^ ]*' /proc/cmdline systemctl get-default sudo systemctl reboot grep -o 'systemd.unit=[^ ]*' /proc/cmdline || echo "gone" - In the rescue boot,
- Practice
Permanent arguments with grubby
For all installed kernels: add
audit=1andloglevel=5, removerhgbandquiet, and make sure there is nocrashkernel=change. Show the resulting arguments fromgrubby, reboot, and confirm the running kernel has them. Then set the default boot entry to the kernel you booted and show it.Check your result
sudo grubby --info=ALL | grep ^argscontainsaudit=1 loglevel=5and notrhgborquiet.- After the reboot,
grep -oE 'audit=1|loglevel=5' /proc/cmdlineprints both;rhgbandquietare absent. sudo grubby --default-kernelprints the path of the running kernel (/boot/vmlinuz-$(uname -r)).
Hint
grubby --update-kernel=ALL --args="a=1 b=2" --remove-args="rhgb quiet". Do not editgrub.cfgby hand on RHEL: the boot entries live in/boot/loader/entries/*.confand the kernel arguments in theoptionsline.Solution
sudo grubby --update-kernel=ALL --args="audit=1 loglevel=5" --remove-args="rhgb quiet" sudo grubby --info=ALL | grep -E '^(index|args)' sudo grubby --set-default /boot/vmlinuz-$(uname -r) sudo grubby --default-kernel sudo systemctl reboot # after the reboot cat /proc/cmdline - Challenge
The kernel entry disappeared
Setup (lab VM):
sudo mkdir -p /root/entries.bak sudo mv /boot/loader/entries/*$(uname -r)*.conf /root/entries.bak/ sudo grubby --info=ALL | grep -c '^kernel'grubbynow shows no usable entry for the running kernel and a reboot would land on the wrong one or on agrub>prompt. Without restoring the file from/root/entries.bak, recreate a correct boot entry from the installed kernel package, make it the default, and prove it withgrubby --info=ALLand a reboot.Check your result
ls /boot/loader/entries/contains an entry for$(uname -r).sudo grubby --default-kernelprints/boot/vmlinuz-$(uname -r).- After a reboot
uname -ris the expected version.
Hint
Entries are created by
kernel-installwhen a kernel package is installed. Reinstalling the kernel core package re-runs it, or callkernel-install add VERSION /lib/modules/VERSION/vmlinuzdirectly. Then regenerate the config only ifgrubbysays it is needed.Solution
sudo kernel-install add $(uname -r) /lib/modules/$(uname -r)/vmlinuz ls /boot/loader/entries/ sudo grubby --info=ALL | grep -E '^(index|kernel|args)' sudo grubby --set-default /boot/vmlinuz-$(uname -r) sudo grub2-mkconfig -o /boot/grub2/grub.cfg sudo systemctl reboot