Manage systemd Services with systemctl

Start, enable, inspect, customize, troubleshoot, and limit systemd services safely with systemctl.

systemd is the service manager used by most current Linux distributions. Its systemctl command controls services and other unit types, including sockets, timers, mounts, paths, devices, and targets.

Official references:

The examples use nginx.service. Replace it with the unit installed on your system.

Check the systemd Version

Display the installed systemd version and enabled features.

systemctl --version

Check whether systemd is PID 1.

ps -p 1 -o pid,comm,args

Display the overall manager status.

systemctl status --no-pager

Understand Unit Names

A complete unit name contains a suffix that identifies its type:

Unit type Example Purpose
Service nginx.service Daemon or process
Socket ssh.socket Socket-based activation
Timer fstrim.timer Scheduled activation
Mount home.mount Filesystem mount
Path example.path Path-based activation
Target multi-user.target Group of units and boot state

For many service commands, systemctl adds .service when the suffix is omitted. Writing the complete name makes scripts and documentation clearer.

Start, Stop, and Restart a Service

Start a service now.

sudo systemctl start nginx.service

Stop it now.

sudo systemctl stop nginx.service

Restart it even if it is currently inactive.

sudo systemctl restart nginx.service

Reload the application’s configuration without restarting its process. This succeeds only when the unit implements a reload operation.

sudo systemctl reload nginx.service

Reload the service when supported, or restart it otherwise.

sudo systemctl reload-or-restart nginx.service

Restart the service only if it is already running.

sudo systemctl try-restart nginx.service

systemctl daemon-reload has a different purpose: it makes the systemd manager reread unit files and dependency definitions. It does not reload an application’s own configuration and does not restart running services.

sudo systemctl daemon-reload

Enable or Disable Automatic Startup

Enabling and starting are separate operations. enable creates the links described by the unit’s [Install] section so it can be activated during boot or by another unit; it does not start the service unless --now is included.

Enable a service for future boots.

sudo systemctl enable nginx.service

Enable and start it in one operation.

sudo systemctl enable --now nginx.service

Disable future automatic startup without stopping the currently running service.

sudo systemctl disable nginx.service

Disable and stop it.

sudo systemctl disable --now nginx.service

Do not manually create links under a target’s .wants directory. systemctl enable reads the unit metadata, creates the correct links, and reloads the manager configuration.

Mask or Unmask a Unit

Masking prevents every form of activation, including manual starts and dependency-based starts. Use it only when a service must not run.

sudo systemctl mask nginx.service

Mask and stop the service immediately.

sudo systemctl mask --now nginx.service

Remove the mask before enabling or starting the unit again.

sudo systemctl unmask nginx.service

Check Service State

Show a human-readable status report with recent log messages.

systemctl status nginx.service

Prevent the output from opening a pager and show untruncated lines.

systemctl status nginx.service --no-pager --full

Use state-check commands in scripts. They print a state and return zero only when the requested condition is true.

systemctl is-active nginx.service
systemctl is-enabled nginx.service
systemctl is-failed nginx.service

Check only the exit status in a shell condition.

if systemctl is-active --quiet nginx.service; then echo running; else echo stopped; fi

An enabled service can be inactive, and an active service can be disabled. The first state controls future activation; the second describes its current runtime state.

Inspect Unit Properties and Files

Display every runtime property known to systemd.

systemctl show nginx.service

Select the most useful properties for troubleshooting.

systemctl show nginx.service --property=LoadState,ActiveState,SubState,UnitFileState,MainPID,Result,ExecMainCode,ExecMainStatus,FragmentPath,DropInPaths

Display the vendor unit file and every applied drop-in in precedence order.

systemctl cat nginx.service

Show the unit’s vendor file path.

systemctl show nginx.service --property=FragmentPath --value

Common system-unit locations are:

Directory Purpose
/etc/systemd/system/ Local administrator units and overrides; highest persistent priority
/run/systemd/system/ Runtime units and overrides removed at reboot
/usr/lib/systemd/system/ Vendor or package-provided units
/lib/systemd/system/ Vendor path used by some distributions

Avoid editing package files under /usr/lib or /lib because upgrades can replace them.

List Services and Unit Files

List currently loaded units. Without --all, inactive units are normally omitted.

systemctl list-units
systemctl list-units --type=service
systemctl list-units --type=service --all

List failed units.

systemctl --failed

List installed unit files and their enablement state, including units that are not currently loaded.

systemctl list-unit-files
systemctl list-unit-files --type=service
systemctl list-unit-files --type=service --state=enabled

List jobs that systemd is currently starting or stopping.

systemctl list-jobs

Check the overall system state. Common results include running, degraded, starting, and maintenance.

systemctl is-system-running

Inspect Dependencies and Ordering

Display the units that the selected service depends on.

systemctl list-dependencies nginx.service

Include all dependency levels.

systemctl list-dependencies nginx.service --all

Display reverse dependencies: units that depend on the selected service.

systemctl list-dependencies nginx.service --reverse

Dependency relationships and start order are different concepts. Requires= and Wants= express dependency strength, while After= and Before= control ordering.

Read Service Logs

Show all retained messages for a service.

sudo journalctl -u nginx.service

Show the last 100 messages from the current boot without a pager.

sudo journalctl -u nginx.service -b -n 100 --no-pager

Follow new messages while reproducing a problem.

sudo journalctl -u nginx.service -n 50 -f

Edit a Service Safely

Use a drop-in to override a package-provided unit. This preserves the vendor file and survives package upgrades.

sudo systemctl edit nginx.service

For example, add restart behavior and a 1 GiB memory throttle with a 1536 MiB hard limit:

[Service]
Restart=on-failure
RestartSec=5s
MemoryHigh=1G
MemoryMax=1536M

Saving systemctl edit installs the drop-in under /etc/systemd/system/nginx.service.d/ and reloads the systemd manager. Restart the service when the changed setting applies only to a new process.

sudo systemctl restart nginx.service

Revert every local drop-in and full-file override created for the unit.

sudo systemctl revert nginx.service

If a unit file is edited manually, validate it and reload the manager before restarting the service.

sudo systemd-analyze verify /etc/systemd/system/example.service
sudo systemctl daemon-reload
sudo systemctl restart example.service

Set Resource Limits

Set persistent cgroup v2 properties without manually editing a drop-in. The changes apply immediately when possible and are saved for future starts.

sudo systemctl set-property nginx.service CPUWeight=200 MemoryHigh=1G MemoryMax=1536M

Use --runtime to keep a test change only until reboot.

sudo systemctl set-property --runtime nginx.service CPUWeight=200 MemoryHigh=1G

Inspect the effective properties.

systemctl show nginx.service --property=CPUWeight,MemoryHigh,MemoryMax,ControlGroup

CPUWeight is the current cgroup v2 replacement for the legacy CPUShares setting. A weight affects relative CPU distribution during contention; it is not a hard CPU limit. Use CPUQuota= when a hard bandwidth limit is required. MemoryHigh= is the preferred throttling control, while MemoryMax= is a last line of defense that can trigger an out-of-memory kill inside the unit.

Create a Custom Service

Create custom system units under /etc/systemd/system/. The example below runs an existing application as a dedicated unprivileged account.

sudoedit /etc/systemd/system/example.service
[Unit]
Description=Example application service
Wants=network-online.target
After=network-online.target

[Service]
Type=exec
User=example
Group=example
WorkingDirectory=/opt/example
ExecStart=/opt/example/bin/example
Restart=on-failure
RestartSec=5s
NoNewPrivileges=yes
PrivateTmp=yes

[Install]
WantedBy=multi-user.target

Use network-online.target only when the application requires a configured network during startup. Many network services can start after network.target or without an explicit network ordering rule.

Systemd does not apply shell syntax to ExecStart by default. Use an absolute executable path and pass arguments directly. Do not add a shell solely for environment-variable expansion or redirection unless the service genuinely requires shell behavior.

Validate, load, enable, and start the unit.

sudo systemd-analyze verify /etc/systemd/system/example.service
sudo systemctl daemon-reload
sudo systemctl enable --now example.service
systemctl status example.service --no-pager --full

The example account, group, working directory, and executable must exist before starting the service.

Manage Template Instances

A template such as worker@.service can create multiple service instances. %i expands to the instance name inside the template.

[Unit]
Description=Worker instance %i

[Service]
Type=exec
ExecStart=/opt/example/bin/worker --instance %i
Restart=on-failure

[Install]
WantedBy=multi-user.target

Enable and start instance 1.

sudo systemctl enable --now worker@1.service

Manage another instance independently.

sudo systemctl start worker@2.service
sudo systemctl status worker@2.service

Manage User Services

User services run under the current user’s service manager and do not require root access. Store custom user units in ~/.config/systemd/user/.

mkdir -p ~/.config/systemd/user
nano ~/.config/systemd/user/example.service
systemctl --user daemon-reload
systemctl --user enable --now example.service
systemctl --user status example.service
journalctl --user -u example.service

By default, a user’s manager may stop after the last login session ends. An administrator can enable lingering when that user’s services must continue without an active login.

sudo loginctl enable-linger username

Recover a Failed Service

Inspect status, logs, the recorded exit result, and the unit definition.

systemctl status nginx.service --no-pager --full
sudo journalctl -u nginx.service -b -p warning -n 100 --no-pager
systemctl show nginx.service --property=Result,ExecMainCode,ExecMainStatus,Restart,StartLimitBurst
systemctl cat nginx.service

After fixing the cause, clear the failed state and start the unit again.

sudo systemctl reset-failed nginx.service
sudo systemctl start nginx.service

If the message says the start request was repeated too quickly, fix the underlying crash before using reset-failed; clearing the counter alone does not correct the service.

Send a Signal to a Service

systemctl kill sends a signal to processes in a unit. Normal service shutdown should use systemctl stop so the unit’s configured stop behavior and timeout are honored.

Send SIGHUP only to the main process when an application documents that signal as a configuration reload request.

sudo systemctl kill --kill-whom=main --signal=SIGHUP nginx.service

Manage the Default Target

Display the target used for a normal boot.

systemctl get-default

Set a text-oriented multi-user boot.

sudo systemctl set-default multi-user.target

Set a graphical boot.

sudo systemctl set-default graphical.target

List installed and currently loaded targets.

systemctl list-unit-files --type=target
systemctl list-units --type=target --all

Traditional runlevel aliases commonly map as follows, although distribution presets can differ:

Runlevel systemd target
0 poweroff.target
1 rescue.target
2, 3, 4 multi-user.target
5 graphical.target
6 reboot.target

Switch the running system to another target with isolate. Units not required by the new target can be stopped, so use a local console before isolating a remote server.

sudo systemctl isolate multi-user.target

Enter rescue or emergency mode from a local console.

sudo systemctl rescue
sudo systemctl emergency

Power and Sleep Commands

The following commands affect the whole machine and can disconnect users or interrupt work.

sudo systemctl reboot
sudo systemctl poweroff
sudo systemctl suspend
sudo systemctl hibernate
sudo systemctl hybrid-sleep
sudo systemctl suspend-then-hibernate

Hibernate and hybrid sleep require supported hardware, sufficient swap, and a correctly configured resume path. Check the journal if the machine returns immediately or fails to resume.

Licensed under CC BY-NC-SA 4.0
Last updated on Thursday, September 24, 2026
comments powered by Disqus