systemd

Last update: 2024-04-14 21:45:03 +0800 +0800
tags: Linux | Systemd
Available translations: 日本語 / 中文(简体) / 中文(繁體)

systemd is a service manager and a suite of Linux system-management components. The system manager runs as PID 1; per-user managers run as systemd --user. Both managers load units, calculate transactions of jobs, and supervise process groups through Linux control groups.

Units, Jobs, and Lifecycle States #

A unit represents a resource known to a manager. Common unit types are:

SuffixResource
.serviceA process or daemon
.socketAn IPC or network socket used for activation
.targetA synchronization and grouping point
.mount, .automount, .swapStorage configuration
.device, .path, .timerDevice or event-based activation
.slice, .scopecgroup organization and externally started processes

A job is a requested unit state change such as start, stop, or reload. Starting one unit can pull in other jobs; the manager combines them into a transaction, checks for ordering cycles and conflicting jobs, and then dispatches independent work in parallel.

Unit state has several dimensions. LoadState records whether the definition loaded; ActiveState reports high-level state such as inactive, activating, active, deactivating, or failed; SubState supplies type-specific detail. A loaded service is not necessarily running, and an enabled service is not necessarily loaded or active. Enabling changes boot or activation links; starting creates a runtime job.

sh
systemctl show sshd.service \
  --property=LoadState,ActiveState,SubState,UnitFileState
systemctl status sshd.service
systemctl list-jobs
systemctl --failed

Requirement and Ordering Dependencies #

Requirement edges determine which units enter a transaction:

  • Requires= pulls in another unit and propagates selected start failures or stops;
  • Wants= is weaker because the requested unit may fail without failing the requester;
  • Requisite= fails if the other unit is not already active;
  • BindsTo= couples activity more tightly to a disappearing resource;
  • Conflicts= schedules the conflicting unit to stop.

Ordering edges determine sequence. After= and Before= do not pull another unit into the transaction, and Requires= or Wants= do not establish order. Express both when both relationships are required:

ini
[Unit]
Wants=network-online.target
After=network-online.target

Ordering is evaluated differently during shutdown: if a unit ordered after another is stopped in the same transaction, it is stopped first.

Managers add implicit and default dependencies based on unit type and settings. For example, mount units acquire relationships to parent mounts, and many service units receive default ordering against basic startup and shutdown targets. Generators create or modify unit definitions early during manager startup; systemd-fstab-generator translates /etc/fstab, and other generators handle kernel command-line and compatibility inputs. Inspect the calculated graph rather than assuming every edge appears literally in one file:

sh
systemctl list-dependencies example.service
systemctl list-dependencies --reverse example.service
systemctl show example.service --property=Wants,Requires,Before,After
systemd-analyze critical-chain

Discovery, Naming, and Overrides #

Unit names encode the type in the suffix. Names derived from paths use systemd escaping: /var/lib becomes var-lib.mount, while / becomes -.mount. Template names such as worker@.service create instances such as worker@blue.service; %i expands to the escaped instance and %I to its unescaped form.

The manager searches a compile-time unit load path. Administrator definitions in /etc/systemd/system take precedence over vendor definitions commonly installed under /usr/lib/systemd/system or /lib/systemd/system; transient and generated directories have defined positions in the same search order. Query the running manager because distributions can differ:

sh
systemd-analyze unit-paths
systemd-analyze --user unit-paths
systemctl cat example.service
systemctl list-unit-files 'example*'

An alias is another valid unit name implemented by a symlink or Alias= during enablement. .wants/ and .requires/ directories encode dependency links. [Install] settings such as WantedBy= and RequiredBy= tell systemctl enable which links to create; the manager does not interpret [Install] while starting a unit.

Never edit a packaged vendor file for a local policy. Create a drop-in:

sh
systemctl edit example.service
systemctl daemon-reload
systemctl restart example.service
systemd-delta

Drop-ins named *.conf are merged lexicographically. Scalar settings replace earlier values, while list settings can accumulate and may require an empty assignment before replacement:

ini
[Service]
ExecStart=
ExecStart=/usr/local/bin/example --foreground

systemctl revert removes local overrides created for a unit. Review the merged definition with systemctl cat before restarting production service.

Service Tracking and cgroups #

systemd places service processes in a unit cgroup. Descendants remain associated with the service even after double-forking, so PID files are not the fundamental tracking mechanism. Slices organize service and scope cgroups hierarchically; resource settings such as CPUWeight=, MemoryMax=, and TasksMax= apply through the kernel cgroup controllers available on the host.

sh
systemctl status example.service
systemd-cgls
systemctl show example.service --property=ControlGroup,MainPID,TasksCurrent

Type=simple treats the ExecStart process as the main process and does not wait for a readiness protocol. Type=exec waits until execution succeeds. Type=notify waits for READY=1 from a service implementing the notification protocol. Type=forking supports traditional self-daemonizing programs, while Type=oneshot waits for the command to exit. Choose a readiness contract that matches the daemon; ordering after a simple service proves only that its process was launched.

Targets, Boot, and Compatibility #

default.target is the normal boot goal. A kernel systemd.unit= argument can select another target for one boot; otherwise the configured default is used:

sh
systemctl get-default
systemctl set-default multi-user.target
systemctl isolate rescue.target

isolate stops units not required by the target and can terminate sessions, so inspect target dependencies before using it remotely. emergency.target and rescue.target provide restricted recovery environments.

Targets group work but do not impose order by themselves. Boot performance and failure diagnosis therefore use both the job graph and timestamps:

sh
systemd-analyze time
systemd-analyze blame
systemd-analyze critical-chain
journalctl -b -p warning

SysV compatibility is distribution-dependent. A generator can wrap legacy init scripts as service units, and familiar commands such as shutdown may be links to systemd tools. Native units provide more precise dependencies, cgroup tracking, activation, and sandboxing; do not assume an init script receives all native service semantics.

logind and User Managers #

systemd-logind tracks seats, login sessions, users, and inhibitor locks using kernel and userspace device/session information. loginctl inspects that state:

sh
loginctl list-sessions
loginctl session-status
loginctl user-status "$USER"

A PAM login commonly starts a user’s user@UID.service, which runs the user manager. User units follow a separate load path and are controlled with systemctl --user. By default, the manager’s lifetime follows login policy. loginctl enable-linger USER requests startup at boot and persistence after the last session; use it deliberately because lingering user services consume resources without an interactive login.

The system and user managers have separate privileges and buses. A user service cannot acquire system-manager authority merely by declaring a unit option, and system services should not depend on a transient desktop session unless that coupling is intentional.

Operational Inspection #

Use the manager’s own interfaces rather than inferring state from files alone:

sh
systemctl list-units --all
systemctl list-unit-files
systemctl cat example.service
systemctl show example.service
systemd-analyze verify /etc/systemd/system/example.service
journalctl --unit=example.service --boot

After changing unit files outside systemctl edit, run systemctl daemon-reload; this reparses definitions but does not restart services. Validate first, reload, inspect the merged unit, and then restart or reload the smallest affected unit. The upstream manuals systemd.unit(5), systemd.service(5), systemd.special(7), and systemd.generator(7) define the version installed on a host.

Comments

Read or comment on GitHub (sign-in required to comment)