Managing Services with systemctl
Operate systemd units deliberately: inspect effective definitions, distinguish runtime state from boot enablement, perform controlled transitions, and verify every result.
Learning objectives
By the end of this lesson
- Distinguish unit load state, active state, substate, enablement, preset, and failure result.
- Inspect effective unit definitions, properties, dependencies, and recent logs before changing state.
- Use start, stop, restart, reload, try-restart, enable, disable, mask, and unmask correctly.
- Explain the difference between system and user service managers.
- Create and operate a safe user service without root privileges.
1. “Is the service running?” is several different questions
systemd manages many unit types: services, sockets, timers, mounts,
automounts, paths, targets, devices, and scopes. For a service,
loaded means systemd found and parsed a definition.
active is a high-level runtime state, while the
substate may be running, exited, listening, dead, or failed.
Enablement describes whether dependency links will pull the unit
into future boot or user-manager transactions. It does not describe
the current process.
flowchart TD A["Unit file and drop-ins"] --> B["Loaded configuration"] B --> C["Enablement links or preset policy"] B --> D["Runtime transaction"] D --> E["Active, inactive, activating, failed"] E --> F["Process, exit result, restart policy"] F --> G["Journal and dependency evidence"]
systemctl statusDefinition parsed and available
systemctl is-activeCurrent runtime state
systemctl is-enabledDependency links or static/indirect state
systemctl is-failedFailure state recorded by manager
systemctl showDetailed properties and result fields
2. Inspect configuration and evidence before transitions
unit=ssh.service # On some systems the unit is sshd.service
systemctl status "$unit" --no-pager
systemctl cat "$unit"
systemctl show "$unit" \
-p LoadState -p ActiveState -p SubState -p UnitFileState \
-p MainPID -p ExecMainStatus -p Result -p FragmentPath -p DropInPaths
systemctl list-dependencies "$unit"
systemctl list-dependencies --reverse "$unit"
journalctl -u "$unit" -b --no-pager -n 100
systemctl cat shows the main fragment and drop-ins in
precedence order. show exposes machine-readable
properties and is better than parsing human-oriented
status output in automation. Reverse dependencies
answer which units may be affected by a stop or failure.
3. Choose the least disruptive transition
Ask the service to re-read supported configuration without replacing the main process.
Stop and start the unit; expect an interruption unless architecture provides redundancy.
Restart only if already active; useful when applying optional changes.
Reload when supported, otherwise restart.
Deactivate the unit and dependent behavior according to relationships.
# Validate application configuration first when a native checker exists
sudo nginx -t
# Then choose the smallest operation that applies the change
sudo systemctl reload nginx.service
# Verify state, result, PID continuity, and recent messages
systemctl is-active nginx.service
systemctl show nginx.service -p MainPID -p ActiveEnterTimestamp -p Result
journalctl -u nginx.service --since "5 minutes ago" --no-pager
A command can return successfully while the workload remains unhealthy, bound to the wrong address, unable to reach dependencies, or serving stale configuration. Verify the service and the user-facing outcome.
4. Runtime state and boot enablement are independent
enable creates links described by the unit's
[Install] section. It does not normally start the unit
unless combined with --now.
disable removes enablement links but does not stop a
running unit. Static units have no independent enablement
instructions and are pulled in by dependencies. Masking links the
unit to /dev/null, preventing manual and
dependency-based activation until unmasked.
# Read-only enablement inspection
systemctl is-enabled cron.service 2>/dev/null || systemctl is-enabled crond.service
systemctl list-unit-files --type=service --state=enabled
# Intentional combined operations
sudo systemctl enable --now example.service
sudo systemctl disable --now example.service
# Mask only with a documented reason and recovery path
sudo systemctl mask example.service
sudo systemctl unmask example.service
Preset policy is a distribution or organization rule applied by
systemctl preset. It can differ from an administrator's
current choice. Avoid running preset-all casually on an established
host.
5. User units provide per-user lifecycle management
systemctl --user communicates with the user's service
manager. User units live under paths such as
~/.config/systemd/user. They do not automatically gain
root privileges. Their environment, login lifecycle, and
availability differ from system units. Lingering can keep a user
manager alive without an active login, but should be enabled only
intentionally.
systemctl --user status --no-pager
systemctl --user list-units --type=service
systemctl --user show-environment | sort | head -n 40
loginctl show-user "$USER" -p Linger -p State 2>/dev/null || true
6. Hands-on lab: create and operate a user service
This service writes a timestamped record inside your course
directory. It uses no sudo and can be removed
completely after the lab.
lab="$HOME/devops-academy/linux/chapter11/lesson02"
unit_dir="$HOME/.config/systemd/user"
mkdir -p "$lab" "$unit_dir"
cat > "$unit_dir/devops-academy-demo.service" <<'UNIT'
[Unit]
Description=DevOps Academy user-service demonstration
[Service]
Type=oneshot
ExecStart=/usr/bin/bash -c 'printf "started=%s user=%s\n" "$(date --iso-8601=seconds)" "$USER" >> %h/devops-academy/linux/chapter11/lesson02/service.log'
RemainAfterExit=yes
[Install]
WantedBy=default.target
UNIT
systemctl --user daemon-reload
systemctl --user start devops-academy-demo.service
systemctl --user status devops-academy-demo.service --no-pager
systemctl --user show devops-academy-demo.service -p ActiveState -p SubState -p Result
cat "$lab/service.log"
# Optional enablement exercise, then return to the original disabled state
systemctl --user enable devops-academy-demo.service
systemctl --user is-enabled devops-academy-demo.service
systemctl --user disable devops-academy-demo.service
systemctl --user stop devops-academy-demo.service
rm -f "$unit_dir/devops-academy-demo.service"
systemctl --user daemon-reload
systemctl --user reset-failed
Verification checklist
7. Common systemctl mistakes
“Enabled means running.”
Enablement affects future activation relationships; active state describes the current manager transaction.
“Restart is the safest way to apply every change.”
Reload may avoid interruption, and some configuration should be validated before either action.
“disable prevents all starts.”
A disabled unit can still be started manually or pulled in by another dependency. Masking is stronger.
“status contains everything.”
Use cat, show, dependency inspection,
and the journal for complete evidence.
8. Knowledge check
Question 1. What is the difference between
enable and start?
enable creates activation links for future
transactions; start activates the unit now.
Question 2. When is reload preferable to
restart?
Question 3. Why inspect reverse dependencies before stopping a unit?
9. Summary
systemctl operates a stateful dependency manager. Reliable service work distinguishes configuration, runtime state, enablement, and failure result; inspects effective definitions and dependencies; chooses the least disruptive transition; and verifies both manager state and workload behavior.
10. Further reading
-
systemctl(1),systemd.unit(5), andsystemd.service(5). -
systemd.preset(5),loginctl(1), and user-manager documentation. - Service-specific configuration-validation and graceful-reload documentation.
Keep the academy open
Support free, practical DevOps education.
Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0
Send only Ethereum/ERC-20 compatible assets to this
address.