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.
grubbygrub2-mkconfig/etc/default/grub/proc/cmdlinegrub2-setpasswordsystemd.unit=systemd-analyze
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:
- Firmware (UEFI or BIOS) initialises hardware and finds the boot loader.
- 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).
- The kernel starts and runs
systemdfrom the initramfs, which locates and mounts the real root file system at/sysroot. - 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
| Way | Scope | Use it for |
|---|---|---|
Edit the entry at the menu (e) | This boot only, in memory | Emergency access, trying a parameter |
grubby | Permanent, written to the entries | Making 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:
| Parameter | Effect |
|---|---|
systemd.unit=rescue.target | Boot into rescue mode (single-user, root file system mounted read-write) |
systemd.unit=emergency.target | Boot into emergency mode (minimal, root read-only) |
rd.break | Stop in the initramfs before the real root is mounted; used to reset the root password (next lesson) |
single or 1 | Older 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.
Menu settings in /etc/default/grub
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.
- 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/cmdlineprintsBOOT_IMAGE=... root=... ro ....grubby --default-kernelprints a path like/boot/vmlinuz-6.12.0-....Hint
/proc/cmdlineis the live value.grubby --info=ALLshows every entry.ls /boot/loader/entrieslists them too.Solution
cat /proc/cmdline grubby --default-kernel grubby --info=ALL | grep -E '^(index|kernel|args)' - Practice
Boot into rescue mode, once
Reboot the lab VM. At the GRUB menu press
e, addsystemd.unit=rescue.targetto the end of the line that begins withlinux, and boot withCtrl+x. Log in with the root password, confirm withsystemctl get-defaultandsystemctl 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=targetshowsrescue.targetand notmulti-user.target. After a normal reboot you are back in the default target, because the edit applies only to that boot.Hint
eedits a menu entry in memory.Ctrl+xboots it. Nothing is written to disk. Usesystemd.unit=emergency.targetfor 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 - Practice
Add a kernel argument permanently
Add the kernel argument
audit=1to 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 argsincludesaudit=1. After rebootgrep -o 'audit=1' /proc/cmdlineprints it. After the removal it is gone fromgrubby --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" - 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/grubshowsGRUB_TIMEOUT=10andgrep timeout= /boot/grub2/grub.cfg(orgrub2-editenv list) agrees.grubby --default-kernelprints the kernel you chose.Hint
Edit
GRUB_TIMEOUTin/etc/default/grub, thensudo grub2-mkconfig -o /boot/grub2/grub.cfg. Choose the default withgrubby --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 - 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-analyzeprintsStartup finished in ... (kernel) + ... (userspace).systemd-analyze blame | head -5shows five units.systemd-analyze critical-chainends atmulti-user.target.Hint
systemd-analyze,systemd-analyze blame,systemd-analyze critical-chain.Solution
systemd-analyze systemd-analyze blame | head -5 systemd-analyze critical-chain