systemd-analyze & Troubleshooting Boot

systemd in Depth

Chapter 10 · systemd-analyze & Troubleshooting Boot

systemd1-1 claimed systemd's parallel, dependency-based startup is faster than System V init's sequential one. This chapter gives you the tools to actually see that claim in practice — and to diagnose it when something goes wrong.

systemd-analyze — The Basic Boot Time Report

systemd-analyze

A first-glance breakdown: kernel time, initrd time, and userspace time — the portion systemd itself is responsible for. A genuinely useful starting point before diving deeper into any specific tool below.

systemd-analyze blame — Which Units Took the Longest

systemd-analyze blame

A sorted list of every unit and how long it individually took to initialize, longest first. A real, important caveat, tying directly back to systemd1-1's own parallel-startup material: a unit taking a long time doesn't necessarily delay the overall boot, if other unrelated units were starting in parallel at the same time. blame shows individual unit duration — not necessarily "this is why your boot is slow."

systemd-analyze critical-chain — The Actual Bottleneck Path

systemd-analyze critical-chain

This is the tool that actually answers "what delayed the overall boot": the critical path — the specific chain of units where each one genuinely had to wait for the one before it, via real dependencies (systemd1-4's own material) — tracing back to the actual longest dependency chain, not just the longest individual unit. A unit can show up near the top of blame (genuinely slow on its own) but never appear on the critical path at all, if it was running in parallel with other things and nothing else was actually waiting on it. This is exactly the resolution to blame's own caveat above.

systemd-analyze plot — Visualizing the Whole Boot

systemd-analyze plot > boot.svg

Generates an actual visual, Gantt-style timeline of every unit's start time and duration — genuinely useful for spotting parallel vs. sequential patterns at a glance, rather than reading through a table of numbers.

Masking vs. Disabling — A Real, Important Distinction

systemd1-2 covered disable — it removes the boot-time symlink, but a disabled unit can still be started manually, or pulled in as a dependency of something else that Wants=/Requires= it. systemctl mask is genuinely stronger: it creates a symlink to /dev/null in place of the unit, making it impossible to start at all — not manually, not as anyone else's dependency, nothing — until explicitly unmasked. The real use case: a unit that's actively causing boot problems and needs to be completely, unconditionally prevented from running while you investigate, not just "not started by default."

A Real Diagnostic Workflow — Slow Boot

  1. systemd-analyze — confirm the boot is genuinely slow
  2. systemd-analyze critical-chain — find the actual bottleneck chain, not just guess from blame
  3. Identify the specific slow unit on that chain
  4. journalctl -u THATUNIT -b (systemd1-6's own tool) — investigate what it was actually doing
  5. If it's not needed at boot at all, systemctl disable it; if it's actively causing harm, systemctl mask it while investigating further

A Real Diagnostic Workflow — Failed Boot / A Unit That Won't Start

systemctl --failed

Lists every unit currently in a failed state — a genuinely fast first step. Then systemctl status THATUNIT (systemd1-2's own tool) for the specific error, then journalctl -u THATUNIT -b for the full detail behind it.

ShowsProves the boot was actually delayed?
blameEach unit's own individual initialization timeNo — could be running in parallel with nothing waiting on it
critical-chainThe actual dependency chain that determined total boot timeYes — this is the real bottleneck path
A "slow" or "failed" unit is sometimes just broken
systemd-analyze verify (systemd1-3's own tool, revisited) is worth running on any unit suspected of being the culprit — a genuine syntax error can look, from the outside, like a mysterious slowdown or failure.
Masking a unit others depend on can cause a cascading failure
Mask deliberately, understanding what depends on the unit first — systemd1-4's own systemctl list-dependencies --reverse is directly relevant again here — not as a reflexive "make the error go away" action.

Hands-On Exercises

Exercise 1

A unit appears near the top of systemd-analyze blame's own output, but does not appear anywhere in systemd-analyze critical-chain's output. Explain what this combination actually tells you about that unit's real impact on boot time.

📄 View solution
Exercise 2

Explain the real difference between systemctl disable myapp and systemctl mask myapp, including a scenario where disable alone would not actually prevent myapp from starting.

📄 View solution
Exercise 3

Write out the full diagnostic workflow (matching this chapter's own numbered sequence) for investigating a boot that has become noticeably slower over the past week, from first command to final action.

📄 View solution

Chapter 10 Quick Reference

  • systemd-analyze — total boot time breakdown (kernel/initrd/userspace)
  • blame — individual unit duration, not proof of overall boot impact
  • critical-chain — the actual dependency chain that determined total boot time; the real diagnostic tool
  • plot — a visual, Gantt-style timeline of the whole boot
  • disable removes the boot-time symlink but allows manual/dependency starts; mask blocks starting entirely, unconditionally
  • Slow boot workflow: analyze → critical-chain → journalctl on the culprit → disable or mask
  • Failed boot workflow: systemctl --failed → status → journalctl
  • Check what depends on a unit (list-dependencies --reverse) before masking it