systemd Operations Manual

18 min read
On this page

Separate running state, permission to start, and installation into boot targets. Examples use the system service example.service; add --user for a user service and inspect that separate manager.

TaskStart here
Service will not startState and evidence
Boot activation or blockingRunning and enabling
Change configuration or executableApplying configuration
Timers and logsTimers and verification

Read state, then the exit reason

Inspect one service

# Read the unit source, runtime state, and recent logs
systemctl status example.service --no-pager

--no-pager prints directly. Read Loaded and its path/errors before Active and the main process. A non-active unit can make status return nonzero without a query failure.

# Compare runtime, exit result, and enablement properties
systemctl show example.service -p ActiveState -p SubState -p Result -p ExecMainStatus -p UnitFileState

ActiveState=failed and Result=exit-code indicate process failure. ExecMainStatus is the main process status; also inspect pre-start commands where relevant.

# Read recent unit logs from this boot
journalctl -u example.service -b -n 80 --no-pager

-u selects the unit, -b this boot, and -n the line count. Use -b -1 for the previous boot or -f to follow live logs as alternatives.

Separate unit diagnosis from inventory

# List units currently recorded as failed
systemctl --failed

After fixing the cause, use sudo systemctl reset-failed example.service if needed to clear failure and start-limit counters. It neither repairs configuration nor starts the application.

# List loaded services including inactive entries
systemctl list-units --all --type=service

For installed unit files and enablement, use systemctl list-unit-files --type=service instead. Loaded units and installed files are different inventories.

ObservationMeaningNext check
active (running)The process is running, not proof of application healthCheck its listener and an application request
active (exited)Often a oneshot unit with RemainAfterExitInspect Type, ExecStart and result
failed / exit-codeA failed result; reset-failed does not fix the causeRead journal and Result, not just the final line
not-foundThis manager did not find the unitCheck name, installation path, and --user scope

Running and enabled are separate dimensions

Preparing the visual
Running and enabled: independent axes

start/stop changes current activity; enable/disable changes activation links. Masking blocks future starts without stopping an already running service.

IntentsystemctlEffect
Start / stop nowstart / stopChanges current runtime state
Install / remove target activationenable / disableManages [Install] symlinks; does not start/stop by itself
Apply bothenable --now / disable --nowChanges both installation and runtime state
Block ordinary activation requestsmask / unmaskMask points to /dev/null; stopping an active unit is separate

Change the current runtime state

# Request an immediate start
sudo systemctl start example.service

Check manager state with systemctl is-active example.service, then test the application. Stop separately with sudo systemctl stop example.service; stopping does not disable future boot activation.

Configure activation through a target

# Install activation links without starting now
sudo systemctl enable example.service

Check is-enabled afterward. Choose enable --now instead to start too. Disable removes links; disable --now also stops. Select the option matching your intent.

Inspect activation paths before masking

# Inspect reverse dependencies among loaded units
systemctl list-dependencies example.service --reverse

Omit --reverse to inspect its dependencies, and check sockets/timers too. This is not exhaustive static analysis of unloaded units. Use sudo systemctl mask example.service only to block activation; unmask reverses it. Verify is-enabled.

A disabled service can still start manually or through dependencies, sockets, or timers. A static unit usually has no [Install] instructions. Masking can conflict with an existing local unit file; inspect it instead of overwriting it.

Unit file or application configuration?

ChangeActionVerify
Manually edited unit / drop-indaemon-reloadInspect parsed values with show; restart when new process settings are needed
Application configurationreloadRequires reload support; connection behavior depends on the application
Need a new processrestartStops and starts; allow for interruption

Inspect before adding an override

# Show the unit and each drop-in source
systemctl cat example.service

Record original values and paths instead of editing distribution-owned files directly. Cat shows disk files; show reports the manager’s loaded properties.

# Create or edit a local drop-in
sudo systemctl edit example.service

Put the following Service fragment in the editor’s active region and save. To cancel, quit without saving. Roll back only this change’s drop-in, then reload/restart and verify; preserve unrelated overrides.

[Service]
Environment=LOG_LEVEL=debug
Restart=on-failure
RestartSec=5s

After a successful systemctl edit, the manager normally reloads unit definitions automatically; manual file edits require daemon-reload. To replace a single ExecStart, clear it with an empty assignment before adding the new command. Keep the actual service arguments.

Validate and load manually edited units

# Validate this local unit and resolvable dependencies
systemd-analyze verify /etc/systemd/system/example.service

Use the actual main unit path from cat; editing a vendor unit does not create a full main file under /etc. Fix validation errors first. Passing does not validate application configuration.

# Reload manually edited unit definitions into the manager
sudo systemctl daemon-reload

This does not recreate service processes. A successful systemctl edit normally already performs the equivalent reload.

# Check the manager’s effective properties
systemctl show example.service -p ExecStart -p Environment -p Restart

Once correct, restart only if a new process is required, then check status/journal and requests. For application configuration supporting reload, choose sudo systemctl reload example.service instead. Do not run both mechanically.

The user manager has separate state

# Query the user service in the intended user session
systemctl --user status example.service --no-pager

User units commonly live in ~/.config/systemd/user/. Run edit/reload/enable --now as that user and inspect journalctl --user -u example.service. Adding sudo may target root’s user manager instead.

Use systemctl --user and journalctl --user for user services. loginctl enable-linger USER allows the user manager to run without an active login; enabling an individual service is a separate operation.

Timers: trigger and execution result

# /etc/systemd/system/example.timer
[Timer]
OnCalendar=daily
Persistent=true
RandomizedDelaySec=30s

[Install]
WantedBy=timers.target
# /etc/systemd/system/example.service
[Service]
Type=oneshot
ExecStart=/usr/local/bin/example-task

Provide the executable task before enabling the timer. Persistent applies to OnCalendar: reactivation can catch up a missed calendar trigger once, not replay every missed run. OnBootSec and OnUnitActiveSec are monotonic timers and do not gain this catch-up behavior.

Validate the schedule and paired units

# Inspect daily and its next scheduled elapse
systemd-analyze calendar daily

Check timezone and expected timing; replace daily with the actual OnCalendar expression. Verify both files with systemd-analyze verify and ensure the task executable exists.

# Load the newly written timer and service
sudo systemctl daemon-reload
# Enable and activate the timer rather than manually starting the service
sudo systemctl enable --now example.timer

Persistent catch-up can run after activation; understand repeated task execution beforehand.

# Check NEXT, LAST, and the activated service
systemctl list-timers --all

NEXT is scheduled time and LAST is activation, not success. Check the service journal and Result/ExecMainStatus. Disable scheduling with sudo systemctl disable --now example.timer; an already-running task is separate.

Separate boot timing from log retention

# Inspect the time-critical dependency chain
systemd-analyze critical-chain example.service

Correlate with journal timestamps; parallel activation and service types affect the timing interpretation.

# Measure journal usage before choosing retention
journalctl --disk-usage

If old logs should be deleted, rotate first with sudo journalctl --rotate, then vacuum-time=7d separately. Save needed evidence first. Configure journald SystemMaxUse and related limits for ongoing retention.

An active timer does not prove the last job succeeded; inspect the service result and journal. journalctl vacuum operations remove archived journals, not a hard cap on total disk use. The blame list alone does not establish the boot critical path.

systemctl · systemd.timer · journalctl