1 of 4

Startup and Boot FailuresLesson 1 of 4

Which boot stage failed? Reading the evidence

Place a boot failure at firmware, boot loader, kernel, initramfs or systemd, and read the previous boot's journal.

  • journalctl
  • journalctl -b -1
  • systemd-analyze
  • systemd-analyze blame
  • systemd-analyze critical-chain
  • systemctl list-jobs
  • systemctl --failed
  • /proc/cmdline
  • mkdir -p /var/log/journal
  • lsblk

40 min3 exercises

After this lesson you can

  • Name the five boot stages and the visible sign that each one failed.
  • Make the journal persistent and read the log of a failed earlier boot.
  • Use systemd-analyze to find what slowed or blocked the last boot.

The idea

A machine that “will not boot” has failed at one specific stage. The stage determines the tools, because each stage can reach only what it has loaded so far. Finding the stage first is half of the repair.

1  Firmware (UEFI/BIOS)   POST, finds a boot device, runs the boot loader (shim + GRUB on RHEL UEFI)
2  Boot loader (GRUB 2)   reads grub.cfg and the BLS entries, loads the kernel and initramfs
3  Kernel                 detects hardware, mounts the initramfs as a temporary root
4  initramfs (dracut)     assembles storage (LVM, LUKS, RAID), finds and mounts the real root, switches to it
5  systemd                starts units to reach default.target: mounts, networking, services, login
StageWhere you see it failWhere the evidence is
1 FirmwareNo boot device, wrong order, Secure Boot rejects the loaderFirmware screen; not in any log
2 GRUBgrub> prompt, grub rescue>, “file not found”, missing entryThe screen only; repair from a rescue system
3 KernelKernel panic, “Unable to mount root fs”, black screen after the kernel loadsConsole text; on the next good boot journalctl -b -1 -k if it got that far
4 initramfsdracut:/# emergency shell, “does not exist” for the root device, timeouts in dracut-initqueueThe shell itself: /run/initramfs/rdsosreport.txt, journalctl in the initramfs
5 systemd“Welcome to emergency mode”, failed units, a long waitThe journal of that boot, readable on the next boot

Stages 1 to 4 happen before the real root file system is available, so there are no files to read unless you boot something else. Stage 5 writes a journal, and with a persistent journal you can read it later.

The journal that survives

By default (Storage=auto), systemd-journald keeps the journal in /run/log/journal, which disappears at reboot. It writes to /var/log/journal only if that directory exists. For troubleshooting boots, create it:

sudo mkdir -p /var/log/journal
sudo systemd-tmpfiles --create --prefix /var/log/journal
sudo systemctl restart systemd-journald

After that journalctl --list-boots shows previous boots and journalctl -b -1 is the one before the current. Do this on a healthy machine, before the problem. A journal that did not exist cannot be read later.

Emergency and rescue

When stage 5 cannot complete, systemd falls back to a smaller target:

TargetWhat is runningUse
rescue.targetBase system, root mounted read-write, other mounts and services started where possibleSingle-user repair when most things work
emergency.targetOnly the root file system, mounted read-only, almost nothing elseWhen even rescue fails; remount with mount -o remount,rw / before editing

Both need the root password (or systemd.debug_shell-style methods) unless you reset it with rd.break. If you do not know the root password, see the initramfs lesson of this skill.

Try it

Read the previous boot

journalctl --list-boots
journalctl -b -1 -p err --no-pager | tail -5
IDX BOOT ID                          FIRST ENTRY                 LAST ENTRY
 -1 4c3b0e7a5f2a4d8b8f6f9b3c4b2f8a1e Wed 2026-11-04 09:10:41 +03 Wed 2026-11-04 09:14:02 +03
  0 b81e0d0c1e8e4f4c9a8c1c7d3e6a5f90 Wed 2026-11-04 09:15:12 +03 Wed 2026-11-04 10:30:55 +03
Nov 04 09:12:11 node1 systemd[1]: dev-disk-by\x2duuid-0000....device: Job dev-disk-by\x2duuid-0000....device/start timed out.
Nov 04 09:12:11 node1 systemd[1]: Timed out waiting for device dev-disk-by\x2duuid-0000....device - /dev/disk/by-uuid/0000....
Nov 04 09:12:11 node1 systemd[1]: Dependency failed for mnt-ghost.mount - /mnt/ghost.

The three lines tell the whole story: a device the system waited for never appeared, the mount that needed it failed, and anything depending on that mount failed after it.

Where did the time go?

systemd-analyze reports the time spent in each stage and unit:

systemd-analyze
systemd-analyze blame | head -4
systemd-analyze critical-chain | head -8
Startup finished in 2.101s (kernel) + 4.882s (initrd) + 95.301s (userspace) = 1min 42.284s
graphical.target reached after 95.201s in userspace.
1min 30.003s dev-disk-by\x2duuid-0000....device
      6.211s NetworkManager-wait-online.service
      3.004s firewalld.service
graphical.target @1min 35.201s
└─multi-user.target @1min 35.200s
  └─mnt-ghost.mount @1min 30.100s +4ms
    └─dev-disk-by\x2duuid-0000....device @1min 30.100s

blame ranks units by their own time. critical-chain shows what actually delayed the target, which is not always the biggest unit: a long unit that runs in parallel costs nothing. Read critical-chain first, then blame.

Check fstab without rebooting

findmnt --verify is a dry-run of /etc/fstab. It reports unreachable devices, wrong file system types and bad options without mounting anything:

findmnt --verify
0 parse errors, 2 errors, 4 warnings
/data
   [E] unreachable on boot required target: No such file or directory
   [E] unreachable on boot required source: UUID=11111111-2222-3333-4444-555555555555
/srv
   [W] unreachable source: /dev/nonexistent: No such file or directory

This is real output from a test fstab with a UUID that does not exist. Run it after every edit of /etc/fstab, before you reboot. An [E] line on a non-nofail entry is a boot that will stop in emergency mode.

Going further

Reading an initramfs failure. If you are at the dracut:/# prompt, cat /run/initramfs/rdsosreport.txt has the dracut log and the state of the storage stack. journalctl works there too, and lsblk and blkid show what the kernel found. Beyond the exam: rd.debug and systemd.log_level=debug on the kernel command line produce very verbose logs of the initramfs and systemd; add them for one boot only, since the output is large.

Practice

0 of 3 done

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

  1. Warm-up

    Which stage is this?

    For each symptom, name the stage that failed and the first check you would make: (1) the machine shows error: file '/boot/grub2/grub.cfg' not found and a grub> prompt; (2) Kernel panic - not syncing: VFS: Unable to mount root fs; (3) a dracut-initqueue timeout, then Warning: /dev/mapper/rhel-root does not exist and a dracut:/# prompt; (4) You are in emergency mode; (5) the login prompt appears after four minutes.

    Check your result
    • (1) boot loader: the boot loader cannot read its configuration; (2) kernel: root device or file system driver missing from the initramfs or wrong root=; (3) initramfs: the storage stack for the root device was not assembled; (4) systemd: a required unit or mount failed; (5) systemd: a slow unit; use systemd-analyze blame.
    Hint

    The prompt tells you who is talking: grub> is GRUB, dracut:/# is the initramfs, a Welcome to emergency mode message is systemd.

    Solution
    1 GRUB            ls (hd0,gpt2)/, then regenerate grub.cfg or reinstall boot files
    2 kernel          check root= on the command line; does the initramfs contain the driver?
    3 initramfs       rd.lvm.lv=, lsblk, does the VG exist? rebuild the initramfs
    4 systemd         journalctl -xb; findmnt --verify; systemctl --failed
    5 systemd         systemd-analyze blame; systemd-analyze critical-chain
  2. Practice

    Make the previous boot readable

    Make the journal persistent so a failed boot can be read after the next reboot. Reboot, then list the boots the journal knows and show the last warnings from the previous boot. Finally print the three units that took longest during the current boot.

    Check your result
    • ls -d /var/log/journal exists (directory) and journalctl --list-boots shows at least two entries after the reboot.
    • journalctl -b -1 -p warning --no-pager | tail prints lines.
    • systemd-analyze blame | head -3 prints three units.
    Hint

    With Storage=auto (the default), journald stores to disk only when /var/log/journal exists. Create it, then systemctl restart systemd-journald or journalctl --flush. History starts from the moment the directory exists.

    Solution
    sudo mkdir -p /var/log/journal
    sudo systemd-tmpfiles --create --prefix /var/log/journal
    sudo systemctl restart systemd-journald
    sudo systemctl reboot
    # after the reboot
    journalctl --list-boots
    journalctl -b -1 -p warning --no-pager | tail
    systemd-analyze blame | head -3
  3. Challenge

    Why does boot wait 90 seconds?

    Setup (lab VM):

    echo '/dev/disk/by-uuid/00000000-0000-0000-0000-000000000000 /mnt/ghost xfs defaults 0 0' | sudo tee -a /etc/fstab
    sudo mkdir -p /mnt/ghost
    sudo systemctl daemon-reload
    sudo systemctl reboot

    The machine drops to emergency mode or waits 90 seconds. Using only evidence, find which mount failed and why, remove the cause in a way that survives the next boot, and show with systemd-analyze that the wait is gone.

    Check your result
    • findmnt --verify reports no [E] lines.
    • systemctl --failed is empty and systemd-analyze blame | head -1 shows no 90 s unit.
    • grep ghost /etc/fstab is empty (or the line carries nofail, with a short x-systemd.device-timeout=).
    Hint

    journalctl -b -p err shows Timed out waiting for device dev-disk-by.... findmnt --verify checks every /etc/fstab line without mounting. Remove the entry or mark it nofail,x-systemd.device-timeout=5 if the device really is optional.

    Solution
    journalctl -b -p err --no-pager | tail -5
    findmnt --verify
    sudo sed -i '\#/mnt/ghost#d' /etc/fstab
    sudo systemctl daemon-reload
    sudo systemctl reboot
    # after the reboot
    systemctl --failed; systemd-analyze blame | head -3