opscape

System and users

systemctl

Start, stop, enable and inspect services and other units managed by systemd.

systemctl [OPTION...] COMMAND [UNIT...]

5 of 16 examples run in Debian 13.7 on 2026-10-31 · manual: systemctl(1)

About these examples: the build sandbox is a container without a running systemd, so most examples on this page were not run and show no output; each says so. The few that work without a running service manager (reading unit files from disk, or showing the error you get in a container) were run for real.

systemctl is the control tool for systemd, the service manager on Debian, Ubuntu, Fedora, Arch and most other current Linux distributions. Everything it manages is a unit: services (nginx.service), timers, sockets, mounts and targets (groups of units, like the old runlevels). You can usually leave off the .service suffix.

Two ideas cover most daily use. A unit's runtime state (start, stop, restart, is-active) is what it is doing now. Its enablement (enable, disable, is-enabled) is whether it starts at boot. They are independent: a service can be running but disabled (gone after the next reboot) or enabled but stopped. enable --now sets both in one go.

Changing system units needs root, so in practice these commands are run with sudo. Units in your own account (~/.config/systemd/user/) are managed with systemctl --user, no root needed. Logs of a unit are read with journalctl.

Examples

Check whether a service is running

systemctl status nginx
explain

Not run in the sandbox: needs a running systemd; not available in the build sandbox. No output is shown because none was captured.

Shows whether the unit is loaded and enabled, its active state (active (running), inactive (dead), failed), main PID, memory use, the process tree, and the last few journal lines. It pipes through a pager in a terminal; add --no-pager in scripts. The exit status is 0 only when the unit is running.

See what happens without a running systemd

systemctl status ssh
explain
outputexit 1
System has not been booted with systemd as init system (PID 1). Can't operate.
Failed to connect to system scope bus via local transport: Host is down

This is the real output inside a container (and on WSL without systemd enabled): the systemctl program exists, but PID 1 is not systemd, so there is nothing to talk to. Start the daemon directly instead, or run the container with systemd as its init.

Start, stop or restart a service

sudo systemctl start nginx
sudo systemctl stop nginx
sudo systemctl restart nginx

Not run in the sandbox: needs a running systemd and root; not available in the build sandbox. No output is shown because none was captured.

These change the runtime state only and print nothing on success. restart stops and starts the service, dropping open connections.

Reload configuration without a restart

sudo systemctl reload nginx
sudo systemctl reload-or-restart nginx

Not run in the sandbox: needs a running systemd and root; not available in the build sandbox. No output is shown because none was captured.

reload runs the unit's ExecReload= command (for nginx, a signal that re-reads the config while keeping connections). It fails if the unit defines no reload action; reload-or-restart falls back to a restart in that case.

Start a service now and at every boot

sudo systemctl enable --now nginx
explain

Not run in the sandbox: needs a running systemd and root; not available in the build sandbox. No output is shown because none was captured.

enable creates the symlinks that pull the unit in at boot (it prints them) and --now also starts it immediately. Without --now, the service only starts on the next boot.

Stop a service and keep it from starting at boot

sudo systemctl disable --now nginx
explain

Not run in the sandbox: needs a running systemd and root; not available in the build sandbox. No output is shown because none was captured.

The reverse: removes the boot symlinks and stops it. Another unit can still start it as a dependency; systemctl mask prevents that too.

Test a service's state in a script

if systemctl is-active --quiet nginx; then
  echo "nginx is up"
else
  echo "nginx is down" >&2
fi

Not run in the sandbox: needs a running systemd; not available in the build sandbox. No output is shown because none was captured.

is-active prints active, inactive, failed and so on, and exits 0 only for active. --quiet suppresses the word so only the exit status is used.

Check whether a service starts at boot

systemctl is-enabled ssh
explain
output
enabled

is-enabled only reads unit files and symlinks on disk, so it works even here, without a running systemd. Other answers include disabled, static (no install section; only started as a dependency) and masked.

List the services enabled at boot

systemctl list-unit-files --type=service --state=enabled
explain
output
UNIT FILE              STATE   PRESET
getty@.service         enabled enabled
ssh.service            enabled enabled
sshd-keygen.service    enabled enabled
systemd-pstore.service enabled enabled

4 unit files listed.

list-unit-files also works from disk alone. It lists installed units with their enablement state; this minimal container has only four enabled services.

List units that have failed

systemctl list-units --failed
explain

Not run in the sandbox: needs a running systemd; not available in the build sandbox. No output is shown because none was captured.

The first command to run after a bad boot. Each failed unit is listed with its description; systemctl status UNIT and journalctl -u UNIT then tell you why. systemctl reset-failed clears the list.

List running services

systemctl list-units --type=service --state=running
explain

Not run in the sandbox: needs a running systemd; not available in the build sandbox. No output is shown because none was captured.

list-units shows units loaded in memory now, unlike list-unit-files, which shows what is installed on disk.

Read a unit's definition

systemctl cat ssh
explain

Not run in the sandbox: needs a running systemd; not available in the build sandbox. No output is shown because none was captured.

Prints the unit file and any drop-in overrides, each preceded by a comment with its path. This is the effective definition, which is what you want when an override is in play.

Read the unit file from disk directly

cat /usr/lib/systemd/system/ssh.service
explain
output
[Unit]
Description=OpenBSD Secure Shell server
Documentation=man:sshd(8) man:sshd_config(5)
After=network.target nss-user-lookup.target auditd.service
ConditionPathExists=!/etc/ssh/sshd_not_to_be_run

[Service]
EnvironmentFile=-/etc/default/ssh
ExecStartPre=/usr/sbin/sshd -t
ExecStart=/usr/sbin/sshd -D $SSHD_OPTS
ExecReload=/usr/sbin/sshd -t
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=on-failure
RestartPreventExitStatus=255
Type=notify
RuntimeDirectory=sshd
RuntimeDirectoryMode=0755

[Install]
WantedBy=multi-user.target
Alias=sshd.service

Without systemd running you can still read the file systemctl cat would show. Package units live in /usr/lib/systemd/system/; your own and overrides go in /etc/systemd/system/, which takes precedence.

Override settings without touching the package file

sudo systemctl edit nginx
sudo systemctl restart nginx

Not run in the sandbox: needs a running systemd, root and an interactive editor; not available in the build sandbox. No output is shown because none was captured.

edit opens an editor on a drop-in file, /etc/systemd/system/nginx.service.d/override.conf, that survives package upgrades, and reloads systemd's configuration when you save. If you change unit files any other way, run sudo systemctl daemon-reload yourself.

Manage your own services without root

systemctl --user daemon-reload
systemctl --user enable --now sync.timer
systemctl --user status sync.timer

Not run in the sandbox: needs a running systemd user manager; not available in the build sandbox. No output is shown because none was captured.

--user talks to your per-user systemd instance, which reads units from ~/.config/systemd/user/. User services stop when you log out unless lingering is enabled (loginctl enable-linger).

Check the systemd version

systemctl --version
explain
output
systemd 257 (257.13-1~deb13u1)
+PAM +AUDIT +SELINUX +APPARMOR +IMA +IPE +SMACK +SECCOMP +GCRYPT -GNUTLS +OPENSSL +ACL +BLKID +CURL +ELFUTILS +FIDO2 +IDN2 -IDN +IPTC +KMOD +LIBCRYPTSETUP +LIBCRYPTSETUP_PLUGINS +LIBFDISK +PCRE2 +PWQUALITY +P11KIT +QRENCODE +TPM2 +BZIP2 +LZ4 +XZ +ZLIB +ZSTD +BPF_FRAMEWORK +BTF -XKBCOMMON -UTMP +SYSVINIT +LIBARCHIVE

Prints the version (257 on Debian 13) and the compile-time features. Works without a running systemd, and is useful when a tutorial relies on a newer option.

Common pitfalls

  • Editing a unit file and restarting without systemctl daemon-reload. systemd keeps using the old definition and warns that the unit file changed on disk.

  • Editing files in /usr/lib/systemd/system/. Package upgrades overwrite them; use systemctl edit or put a full copy in /etc/systemd/system/.

  • Using enable and expecting the service to be running. enable only affects boot; add --now or run start.

  • Parsing systemctl status output in scripts. Use is-active, is-enabled, is-failed and their exit statuses, or systemctl show -p ActiveState --value UNIT.

  • Running systemctl inside a Docker container and getting System has not been booted with systemd. Containers normally run one process directly, not a service manager.

GNU vs BSD and macOS

The examples above ran the GNU/Linux version. These are the differences that matter on macOS and the BSDs (written from their documentation, not run here).

  • systemd is Linux-only. macOS uses launchctl with launchd plists; FreeBSD uses service NAME start and sysrc NAME_enable=YES; Alpine and Gentoo use OpenRC (rc-service, rc-update).

Options worth knowing

A selection, described in our own words. For the full list, see systemctl(1) or systemctl --help.

OptionWhat it does
--nowWith enable or disable, also start or stop the unit.
--userTalk to the calling user's service manager instead of the system one.
--systemTalk to the system service manager (the default).
-t, --type TYPEOnly list units of this type, such as service or timer.
--state STATEOnly list units in this state, such as running, failed or enabled.
--failedList only failed units.
-a, --allInclude inactive units and empty properties in listings.
-q, --quietPrint less; with is-active and friends, nothing at all.
--no-pagerDo not pipe output into a pager.
-l, --fullDo not truncate long lines.
-n, --lines NNumber of journal lines status shows.
-p, --property NAMEOnly show this property with show.
--valueWith show, print property values without the NAME= prefix.
-H, --host HOSTOperate on a remote machine over ssh.
--versionPrint the systemd version and features.

Subcommands

statusShow a unit's state, main process and latest log lines.
startStart a unit now.
stopStop a unit now.
restartStop and start a unit.
reloadAsk a service to re-read its configuration.
reload-or-restartReload if the unit supports it, otherwise restart.
enableMake a unit start at boot (with --now, also start it).
disableStop a unit from starting at boot (with --now, also stop it).
maskPrevent a unit from being started at all.
unmaskUndo mask.
is-activeExit 0 if the unit is running; print its state.
is-enabledExit 0 if the unit is enabled; print its enablement state.
is-failedExit 0 if the unit is in the failed state.
list-unitsList units loaded in memory.
list-unit-filesList installed unit files and their enablement.
list-timersList timers and when they fire next.
catPrint a unit's file and its drop-ins.
editCreate or edit a drop-in override for a unit.
showPrint a unit's properties as NAME=value lines.
daemon-reloadRe-read all unit files after changing them.
reset-failedClear the failed state of units.

Related