3 of 4

Services, Targets and BootLesson 3 of 4

The boot process and the GRUB boot loader

Follow a boot from firmware to target, boot once into a chosen target from the GRUB menu, and change boot loader settings permanently.

  • grubby
  • grub2-mkconfig
  • /etc/default/grub
  • /proc/cmdline
  • grub2-setpassword
  • systemd.unit=
  • systemd-analyze

45 min5 exercises

After this lesson you can

  • Describe the stages of a RHEL boot and name the file or tool involved at each one.
  • Edit the kernel command line at the GRUB menu to boot once into rescue or emergency mode.
  • Change kernel arguments, the default entry and the menu timeout permanently with grubby and /etc/default/grub.

The idea

Everything that goes wrong before a login prompt has to be fixed from the boot loader, so know the stages:

  1. Firmware (UEFI or BIOS) initialises hardware and finds the boot loader.
  2. GRUB2 shows the menu, loads the chosen kernel and the initramfs (a small temporary root file system with the drivers needed to find the real one).
  3. The kernel starts and runs systemd from the initramfs, which locates and mounts the real root file system at /sysroot.
  4. systemd switches to the real root and starts the units for the default target.

Boot menu entries on RHEL follow the Boot Loader Specification: one small file per kernel in /boot/loader/entries/, each with linux, initrd and options lines. The options line is the kernel command line you see in /proc/cmdline. The main configuration file is /boot/grub2/grub.cfg, generated rather than edited by hand, and /etc/default/grub holds the settings that feed the generator.

Two ways to change the command line

WayScopeUse it for
Edit the entry at the menu (e)This boot only, in memoryEmergency access, trying a parameter
grubbyPermanent, written to the entriesMaking a change stick

At the menu: highlight the entry, press e, find the line starting with linux, go to its end, type your parameter, press Ctrl+x to boot. Common parameters:

ParameterEffect
systemd.unit=rescue.targetBoot into rescue mode (single-user, root file system mounted read-write)
systemd.unit=emergency.targetBoot into emergency mode (minimal, root read-only)
rd.breakStop in the initramfs before the real root is mounted; used to reset the root password (next lesson)
single or 1Older spelling for rescue mode

Try it

cat /proc/cmdline
grubby --default-kernel
BOOT_IMAGE=(hd0,gpt2)/vmlinuz-6.12.0-55.el10.x86_64 root=/dev/mapper/rhel-root ro crashkernel=2G-64G:256M,64G-:512M resume=/dev/mapper/rhel-swap rd.lvm.lv=rhel/root rd.lvm.lv=rhel/swap rhgb quiet
/boot/vmlinuz-6.12.0-55.el10.x86_64

Notice ro: the root file system is first mounted read-only and remounted read-write once the system is up. That detail matters when you reset a password.

Permanent changes with grubby

sudo grubby --update-kernel=ALL --args="audit=1"
sudo grubby --info=ALL | grep '^args'
sudo grubby --update-kernel=ALL --remove-args="audit=1"
args="ro crashkernel=2G-64G:256M,64G-:512M resume=/dev/mapper/rhel-swap rd.lvm.lv=rhel/root rd.lvm.lv=rhel/swap rhgb quiet audit=1"

--update-kernel=ALL covers existing and, by updating the default arguments, future kernels. Use a path (--update-kernel=/boot/vmlinuz-6.12.0-55.el10.x86_64) to touch one entry. grubby --info=ALL prints every entry with its index, kernel, arguments and initrd. --set-default PATH chooses the entry that boots without a keypress.

GRUB_TIMEOUT=5
GRUB_DEFAULT=saved
GRUB_DISABLE_RECOVERY="true"
GRUB_CMDLINE_LINUX="crashkernel=auto resume=/dev/mapper/rhel-swap rhgb quiet"

After editing, regenerate the configuration or nothing changes:

sudo grub2-mkconfig -o /boot/grub2/grub.cfg
Generating grub configuration file ...
Adding boot menu entry for UEFI Firmware Settings ...
done

On RHEL this path is correct for both BIOS and UEFI machines. Use grubby for kernel arguments and /etc/default/grub plus grub2-mkconfig for menu timeout and similar settings; mixing the two up is how people think they changed something and then reboot to find they didn’t.

Where did the time go?

systemd-analyze
systemd-analyze blame | head -3
Startup finished in 1.912s (kernel) + 4.201s (initrd) + 9.870s (userspace) = 15.983s
multi-user.target reached after 9.841s in userspace.
5.214s dnf-makecache.service
2.907s NetworkManager-wait-online.service
1.455s firewalld.service

Going further

grub2-editenv list shows the saved default. grubby --info=ALL and the files in /boot/loader/entries are two views of the same data. dracut --force rebuilds the initramfs for the running kernel, which you need after adding drivers to boot. If a new kernel fails, pick the previous entry in the GRUB menu: that’s why installonly_limit=3 in DNF keeps several kernels. Secure Boot, kdump (crashkernel= above) and console=ttyS0 for serial consoles all work by adding arguments to the same line.

Practice

0 of 5 done

Do these on your own system. They get harder. Check each result, then tick it off.

  1. Warm-up

    What did the kernel start with?

    Show the command line the running kernel was booted with, list the installed kernels, and show which one is the default.

    Check your result

    cat /proc/cmdline prints BOOT_IMAGE=... root=... ro .... grubby --default-kernel prints a path like /boot/vmlinuz-6.12.0-....

    Hint

    /proc/cmdline is the live value. grubby --info=ALL shows every entry. ls /boot/loader/entries lists them too.

    Solution
    cat /proc/cmdline
    grubby --default-kernel
    grubby --info=ALL | grep -E '^(index|kernel|args)'
  2. Practice

    Boot into rescue mode, once

    Reboot the lab VM. At the GRUB menu press e, add systemd.unit=rescue.target to the end of the line that begins with linux, and boot with Ctrl+x. Log in with the root password, confirm with systemctl get-default and systemctl list-units --type=target, then reboot normally. Explain why the next boot is not in rescue mode.

    Check your result

    In rescue mode systemctl list-units --type=target shows rescue.target and not multi-user.target. After a normal reboot you are back in the default target, because the edit applies only to that boot.

    Hint

    e edits a menu entry in memory. Ctrl+x boots it. Nothing is written to disk. Use systemd.unit=emergency.target for an even smaller environment.

    Solution
    1. Reboot. At the GRUB menu highlight the first entry and press e.
    2. Move to the line that starts with "linux". Press End.
    3. Add a space and:  systemd.unit=rescue.target
    4. Press Ctrl+x to boot with the edited entry.
    5. Enter the root password at the prompt.
    6. systemctl get-default; systemctl list-units --type=target
    7. systemctl reboot
  3. Practice

    Add a kernel argument permanently

    Add the kernel argument audit=1 to all installed kernels, verify it appears in the configuration, reboot, and check that it appears in /proc/cmdline. Then remove it again the same way.

    Check your result

    grubby --info=ALL | grep args includes audit=1. After reboot grep -o 'audit=1' /proc/cmdline prints it. After the removal it is gone from grubby --info=ALL.

    Hint

    grubby --update-kernel=ALL --args="audit=1" and --remove-args="audit=1".

    Solution
    sudo grubby --update-kernel=ALL --args="audit=1"
    sudo grubby --info=ALL | grep args
    sudo reboot
    # after the reboot
    grep -o 'audit=1' /proc/cmdline
    sudo grubby --update-kernel=ALL --remove-args="audit=1"
  4. Practice

    Change the menu timeout and default entry

    Set the GRUB menu to wait 10 seconds, regenerate the configuration, and make the second installed kernel the default entry (if there is only one, set it explicitly anyway). Verify both settings.

    Check your result

    grep GRUB_TIMEOUT /etc/default/grub shows GRUB_TIMEOUT=10 and grep timeout= /boot/grub2/grub.cfg (or grub2-editenv list) agrees. grubby --default-kernel prints the kernel you chose.

    Hint

    Edit GRUB_TIMEOUT in /etc/default/grub, then sudo grub2-mkconfig -o /boot/grub2/grub.cfg. Choose the default with grubby --set-default /boot/vmlinuz-VERSION.

    Solution
    sudo sed -i 's/^GRUB_TIMEOUT=.*/GRUB_TIMEOUT=10/' /etc/default/grub
    sudo grub2-mkconfig -o /boot/grub2/grub.cfg
    grubby --info=ALL | grep -E '^(index|kernel)'
    sudo grubby --set-default /boot/vmlinuz-$(uname -r)
    grubby --default-kernel
  5. Challenge

    Where did the boot time go?

    Report the time the boot took split into firmware, loader, kernel and userspace, list the five slowest units, and show the chain of units that delayed multi-user.target.

    Check your result

    systemd-analyze prints Startup finished in ... (kernel) + ... (userspace). systemd-analyze blame | head -5 shows five units. systemd-analyze critical-chain ends at multi-user.target.

    Hint

    systemd-analyze, systemd-analyze blame, systemd-analyze critical-chain.

    Solution
    systemd-analyze
    systemd-analyze blame | head -5
    systemd-analyze critical-chain