System and users
systemctl
Start, stop, enable and inspect services and other units managed by systemd.
systemctl [OPTION...] COMMAND [UNIT...]
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
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
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
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
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
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
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
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
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
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
[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
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; usesystemctl editor put a full copy in/etc/systemd/system/.Using
enableand expecting the service to be running.enableonly affects boot; add--nowor runstart.Parsing
systemctl statusoutput in scripts. Useis-active,is-enabled,is-failedand their exit statuses, orsystemctl show -p ActiveState --value UNIT.Running
systemctlinside a Docker container and gettingSystem 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
launchctlwith launchd plists; FreeBSD usesservice NAME startandsysrc 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.
| Option | What it does |
|---|---|
--now | With enable or disable, also start or stop the unit. |
--user | Talk to the calling user's service manager instead of the system one. |
--system | Talk to the system service manager (the default). |
-t, --type TYPE | Only list units of this type, such as service or timer. |
--state STATE | Only list units in this state, such as running, failed or enabled. |
--failed | List only failed units. |
-a, --all | Include inactive units and empty properties in listings. |
-q, --quiet | Print less; with is-active and friends, nothing at all. |
--no-pager | Do not pipe output into a pager. |
-l, --full | Do not truncate long lines. |
-n, --lines N | Number of journal lines status shows. |
-p, --property NAME | Only show this property with show. |
--value | With show, print property values without the NAME= prefix. |
-H, --host HOST | Operate on a remote machine over ssh. |
--version | Print the systemd version and features. |
Subcommands
status | Show a unit's state, main process and latest log lines. |
start | Start a unit now. |
stop | Stop a unit now. |
restart | Stop and start a unit. |
reload | Ask a service to re-read its configuration. |
reload-or-restart | Reload if the unit supports it, otherwise restart. |
enable | Make a unit start at boot (with --now, also start it). |
disable | Stop a unit from starting at boot (with --now, also stop it). |
mask | Prevent a unit from being started at all. |
unmask | Undo mask. |
is-active | Exit 0 if the unit is running; print its state. |
is-enabled | Exit 0 if the unit is enabled; print its enablement state. |
is-failed | Exit 0 if the unit is in the failed state. |
list-units | List units loaded in memory. |
list-unit-files | List installed unit files and their enablement. |
list-timers | List timers and when they fire next. |
cat | Print a unit's file and its drop-ins. |
edit | Create or edit a drop-in override for a unit. |
show | Print a unit's properties as NAME=value lines. |
daemon-reload | Re-read all unit files after changing them. |
reset-failed | Clear the failed state of units. |
Related
journalctlRead and filter the systemd journal, the log store for services, the kernel and the boot process.psPrint a snapshot of running processes, with the columns, filters and sort order you choose.killSend a signal to processes by PID or job number; by default TERM, which asks a process to exit.pgrepPrint the PIDs of processes whose name (or full command line) matches a pattern, with filters by user, parent and age.