When debugging systemd boot failures or service startup issues, understanding the actual execution order of units is crucial. While systemd-analyze
provides basic timing information, it doesn't show the resolved dependency tree that actually executed during operation.
The closest built-in solution is systemd-analyze dot
, which generates a Graphviz-compatible dependency graph:
systemd-analyze dot --from-pattern='*.target' --to-pattern='*.service' | dot -Tsvg > deps.svg
However, this shows potential dependencies rather than the actual execution path.
To see the actual execution order, we need to examine systemd's journal and cgroup information:
journalctl -b -o short-monotonic | grep -E 'Starting|Started'
For a more structured approach, inspect unit dependencies:
systemctl list-dependencies --all your-unit.service
The systemd-bootchart
tool provides a visual timeline of the boot process:
bootctl status
systemd-analyze plot > bootplot.svg
Here's a Python script to generate an execution tree from journal logs:
#!/usr/bin/env python3
import systemd.journal
import networkx as nx
def build_execution_tree():
j = systemd.journal.Reader()
j.seek_realtime(datetime.now() - timedelta(minutes=5))
G = nx.DiGraph()
current_parent = None
for entry in j:
if 'MESSAGE' in entry:
if 'Starting' in entry['MESSAGE']:
unit = entry['MESSAGE'].split(' ')[-1]
G.add_node(unit)
if current_parent:
G.add_edge(current_parent, unit)
current_parent = unit
elif 'Started' in entry['MESSAGE']:
current_parent = None
return G
When debugging a failed multi-user.target:
systemd-analyze critical-chain multi-user.target
systemctl list-dependencies --after multi-user.target
journalctl -u failed-service.service -b
For complex cases, consider:
- Enabling systemd debug logging with
systemd.log_level=debug
- Using
systemd-analyze dump
for low-level state inspection - Building custom visualization with systemd's D-Bus API
When troubleshooting systemd boot issues, seeing the actual execution order of units after dependency resolution can be invaluable. While systemctl list-dependencies
shows static relationships, we need dynamic execution tracing.
Systemd provides several built-in tools for execution analysis:
# Show time-critical chain
systemd-analyze critical-chain
# Generate SVG of boot process
systemd-analyze plot > boot.svg
# Detailed timing breakdown
systemd-analyze blame
For the complete dependency-resolved execution tree, combine these techniques:
# 1. Get the full unit list with states
journalctl --list-boots
systemctl list-units --all --state=failed
# 2. Extract the execution graph
systemd-analyze dot | dot -Tsvg > execution_graph.svg
# 3. Filter for specific units (e.g., network.target)
systemd-analyze dot network.target | dot -Tpng > network_deps.png
When a service fails to start during boot:
# Find which units were active when failure occurred
journalctl -b -1 --unit=my-failed-service.service
# See what was supposed to start next
systemd-analyize verify my-failed-service.service
# Check ordering requirements
systemctl show my-failed-service.service -p After -p Before
For visual timeline analysis:
sudo apt install bootchart
sudo systemctl enable systemd-bootchart
Reboot and check /var/log/bootchart/
for process trees and timing diagrams.
For advanced users, systemd's internal state can be inspected:
# Dump complete state (warning: verbose)
busctl introspect org.freedesktop.systemd1 /org/freedesktop/systemd1
# Monitor job queue in real-time
busctl monitor org.freedesktop.systemd1
Combine these techniques to build a complete picture of your system's initialization sequence and pinpoint exactly where failures occur in the dependency tree.