Processes, boot, and what systemd started
Domain 1 is 23% of XK0-006 and storage is only half of it. This guide covers the other half on both families: reading where the boot time actually went, what a target is made of, the process states the exam asks about, the difference between TERM and KILL demonstrated on a process that refuses one of them, and what each package manager knows about systemd itself.
System Management Guide 10 of 28 Intermediate
- PlatformsUbuntu 26.04 LTS + AlmaLinux 10.2
- Mandatory access controlAppArmor on Ubuntu, SELinux enforcing on Alma
- Firewallufw / nftables 1.1.6
- TimeAbout 24 min
| Server Name | IP Address | OS | Roles | CPU | RAM | HDD |
|---|---|---|---|---|---|---|
| LPLUS-A01 | 192.168.0.73 | Ubuntu 26.04 LTS | Debian-family host - apt, ufw, netplan, AppArmor | 2 Core | 4 GB | 50 GB |
| LPLUS-B01 | 192.168.0.74 | AlmaLinux 10.2 | RPM-family host - dnf, firewalld, NetworkManager, SELinux | 2 Core | 4 GB | 50 GB |
This guide includes
Use this when a machine is slow to boot, when a service will not stop, or when you need to say which package owns a running program. This matters because the tool everyone reaches for to explain a slow boot - systemd-analyze blame - answers a different question from the one being asked.
- reading boot time in three phases, and comparing two families that differ by 13 seconds
- seeing why
blameandcritical-chaindisagree, on a unit slower than the whole boot - finding what a target is made of, and counting running and failed units
- reading process state letters, and watching TERM be caught, ignored, and then overridden by KILL
- asking each package manager what owns
systemctl, and what it shipped
Before you start
- a-disk-a-filesystem-and-a-mount-that-survives
-
What started, in what order, and what it cost
Three phases, and the unit that looks slower than the whole boot.
bash Example session systemd-analyze; echo "---"; systemd-analyze blame | head -5Startup finished in 626ms (kernel) + 1.248s (initrd) + 5.045s (userspace) = 6.920sgraphical.target reached after 4.987s in userspace.---9.269s apt-daily-upgrade.service2.398s snapd.seeded.service2.054s xfs_scrub_all.service1.743s dev-rfkill.device1.743s sys-devices-virtual-misc-rfkill.devicesystemd-analyze critical-chain 2>/dev/null | head -8The time when unit became active or started is printed after the "@" character.The time the unit took to start is printed after the "+" character. graphical.target @4.987s└─multi-user.target @4.987s └─snapd.seeded.service @2.588s +2.398s └─basic.target @2.558s └─sockets.target @2.558ssystemd-analyze; systemd-analyze blame | head -3; echo "--- the same three commands on the RPM family"Startup finished in 4.445s (kernel) + 2.027s (initrd) + 13.325s (userspace) = 19.799sgraphical.target reached after 13.295s in userspace.19.114s fwupd.service11.036s plymouth-quit-wait.service 9.909s kdump.service--- the same three commands on the RPM familyExpected result6.920s total on the Debian host - 626ms kernel, 1.248s initrd, 5.045s userspace - with
apt-daily-upgrade.serviceblamed for 9.269s. Then the critical chain, and 19.799s on the RPM host with 4.445s of it in the kernel.Success conditionYou can say where a boot's time went and which unit actually held it up.
-
The target it boots into, and the units behind it
A target is a set, and several are active at once.
bash Example session systemctl get-default; systemctl list-units --type=target --state=active --no-pager --no-legend | awk '{print $1}' | head -6graphical.targetbasic.targetboot-complete.targetcloud-config.targetcryptsetup.targetgetty-pre.targetgetty.targetsystemctl list-dependencies multi-user.target --no-pager 2>/dev/null | head -8; echo "--- a target is a set of units, not a mode"multi-user.target● ├─apport.service● ├─chrony.service● ├─console-setup.service● ├─cron.service● ├─dbus.service○ ├─dmesg.service○ ├─e2scrub_reap.service--- a target is a set of units, not a modesystemctl list-units --type=service --state=running --no-pager --no-legend | wc -l; echo "running services"; systemctl --failed --no-pager --no-legend | wc -l; echo "failed units"21running services0failed unitsExpected result
graphical.targetas the default, eight active targets listed at once, a dependency tree of individual services, then 21 running services and 0 failed units.Success conditionYou can explain what the machine boots into and what that actually starts.
-
A process, its state, and the signal that stops it
State letters counted across the machine, then TERM caught and TERM ignored.
bash Example session printf '#!/bin/sh\necho $$ > /tmp/sleeper.pid\ntrap "echo caught TERM; exit 0" TERM\nwhile :; do sleep 1; done\n' > /tmp/sleeper.sh && chmod +x /tmp/sleeper.sh && nohup /tmp/sleeper.sh > /tmp/sleeper.log 2>&1 < /dev/null & sleep 2; ps -o pid,stat,comm -p $(cat /tmp/sleeper.pid) PID STAT COMMAND 33063 SN sleeper.shps -eo stat --no-headers | cut -c1 | sort | uniq -c | sort -rn | head -5; echo "--- the state letters, counted across every process on the machine" 64 S 58 I 3 R--- the state letters, counted across every process on the machinekill -TERM $(cat /tmp/sleeper.pid); sleep 1; cat /tmp/sleeper.log; ps -o pid= -p $(cat /tmp/sleeper.pid) 2>/dev/null | wc -l; echo "processes left"caught TERM0processes leftprintf '#!/bin/sh\necho $$ > /tmp/stubborn.pid\ntrap "" TERM\nwhile :; do sleep 1; done\n' > /tmp/stubborn.sh && chmod +x /tmp/stubborn.sh && nohup /tmp/stubborn.sh > /dev/null 2>&1 < /dev/null & sleep 2; kill -TERM $(cat /tmp/stubborn.pid); sleep 1; ps -o pid= -p $(cat /tmp/stubborn.pid) | wc -l; echo "still alive after TERM"; kill -KILL $(cat /tmp/stubborn.pid); sleep 1; ps -o pid= -p $(cat /tmp/stubborn.pid) 2>/dev/null | wc -l; echo "after KILL"1still alive after TERM0after KILLExpected result
SNfor the sleeper, then 64 S, 58 I and 3 R across the machine. TERM producescaught TERMand the process is gone - and the second script survives TERM, needing KILL.Success conditionYou can read a process state and choose the right signal to stop it.
-
The packages behind all of it
The same question - what owns this program - asked in both dialects.
bash Example session dpkg -S $(command -v systemctl) | cut -d: -f1; dpkg -l systemd | tail -1 | awk '{print $2, $3}'; apt-get -s install systemd 2>&1 | tail -1systemdsystemd 259.5-0ubuntu3.40 upgraded, 0 newly installed, 0 to remove and 54 not upgraded.rpm -qf $(command -v systemctl); rpm -q --queryformat '%{NAME} %{VERSION}-%{RELEASE}\n' systemd; echo "--- and what it installed:"; rpm -ql systemd | wc -l; echo "files"systemd-257-23.el10_2.1.alma.1.x86_64systemd 257-23.el10_2.1.alma.1--- and what it installed:952filesrpm -q --changelog systemd 2>/dev/null | head -3; echo "--- the RPM family keeps the changelog in the package, which dpkg does not"* Wed May 20 2026 Andrew Lukoshko <alukoshko@almalinux.org> - 257-23.1.alma.1- Debrand for AlmaLinux --- the RPM family keeps the changelog in the package, which dpkg does notExpected result
systemdand version259.5-0ubuntu3.4on the Debian host with 54 not upgraded;systemd-257-23.el10_2.1.alma.1.x86_64on the RPM host with 952 files - and a changelog entry readingDebrand for AlmaLinux.Success conditionYou can identify the package behind any running program on either family.
-
Putting the machine back
Two scripts removed, and the health check repeated.
zsh Example session rm -f /tmp/sleeper.sh /tmp/sleeper.pid /tmp/sleeper.log /tmp/stubborn.sh /tmp/stubborn.pid; ls /tmp/sleeper* /tmp/stubborn* 2>&1 | tail -1; systemctl --failed --no-pager --no-legend | wc -l; echo "failed units, unchanged"zsh:2: no matches found: /tmp/sleeper*0failed units, unchangedExpected result
zsh: no matches found: /tmp/sleeper*- the glob failing because the files are gone - and 0 failed units, unchanged from the start.Success conditionThe machine carries nothing from this page, and its unit health is where it started.
Troubleshooting
A machine boots slowly and disabling the unit at the top of
blamechanges nothing.Why:
blamesorts units by their own duration, including ones that started after the boot completed and that nothing waited for.Fix:
systemd-analyze critical-chainshows the units that actually delayed the boot, with@for when each became active and+for how long it took. Only those are worth attacking.A process ignores
killand stays in the process list.Why: Plain
killsends TERM, which a process may trap or ignore. A process in stateDmay also be blocked in the kernel and unable to act on any signal.Fix:
kill -KILL <pid>cannot be caught or ignored. If even that leaves the process, check its state withps -o pid,stat,wchan- aDstate means it is waiting on IO and the storage layer is the real problem.A server boots into a graphical target with no desktop installed.
Why: The image was built with
graphical.targetas the default, which simply pulls inmulti-user.targetand finds nothing further to start.Fix:
systemctl set-default multi-user.target, thensystemctl get-defaultto confirm. It costs nothing to leave, but the exam expects you to be able to change it.You need the changelog for an installed package and
dpkghas no option for it.Why: The RPM format stores the changelog in package metadata; the Debian format ships it as a file.
Fix:RPM:
rpm -q --changelog <package>. Debian:zless /usr/share/doc/<package>/changelog.Debian.gz, orapt changelog <package>where the archive provides it.