Linux systemctl Command
last modified October 23, 2026
The systemctl command controls systemd, the init system and
service manager of most current Linux distributions. It starts, stops, and
restarts services, enables them at boot, shows their status, and manages
other kinds of units such as timers, sockets, mounts, and targets.
The basic syntax is systemctl [options] command [unit...].
Commands that change the system need root privileges, so they are run with
sudo; reading the state works for regular users. The examples
were run on Debian 12 with systemd 252, on a machine called
webserver that runs nginx, cron, and an SSH server. The
.service suffix can be omitted: nginx means
nginx.service.
Checking the system state
The is-system-running command reports the overall state of
the service manager.
systemctl is-system-running
running means that the system has fully started and no unit
has failed. Other common values are starting during boot and
degraded when at least one unit has failed; an example
follows later.
$ systemctl is-system-running running
Listing running services
The list-units command lists the units that systemd has in
memory. The --type and --state options filter
the list.
systemctl list-units --type=service --state=running
LOAD tells whether the unit file was read successfully,
ACTIVE is the general state (active,
inactive, failed), and SUB the
detailed one, such as running or exited. In a
terminal, systemctl pipes long output through a pager; the
--no-pager option turns that off.
$ systemctl list-units --type=service --state=running UNIT LOAD ACTIVE SUB DESCRIPTION cron.service loaded active running Regular background program processing daemon dbus.service loaded active running D-Bus System Message Bus nginx.service loaded active running A high performance web server and a reverse proxy server ssh.service loaded active running OpenBSD Secure Shell server systemd-journald.service loaded active running Journal Service systemd-logind.service loaded active running User Login Management LOAD = Reflects whether the unit definition was properly loaded. ACTIVE = The high-level unit activation state, i.e. generalization of SUB. SUB = The low-level unit activation state, values depend on unit type. 6 loaded units listed.
Status of a service
The status command is the first thing to check when a service
misbehaves.
systemctl status nginx
The Loaded line shows the unit file, whether the service is
enabled at boot, and the vendor preset. Active shows the state
and how long it has lasted. Below are the main PID, the number of tasks,
memory and CPU usage, and the process tree of the service's control group.
The last lines come from the journal and often explain why a service
failed. The dot before the name is green for an active unit.
$ systemctl status nginx
● nginx.service - A high performance web server and a reverse proxy server
Loaded: loaded (/lib/systemd/system/nginx.service; enabled; preset: enabled)
Active: active (running) since Fri 2026-10-23 13:37:49 CEST; 3s ago
Docs: man:nginx(8)
Process: 78 ExecStartPre=/usr/sbin/nginx -t -q -g daemon on; master_process on; (code=exited, status=0/SUCCESS)
Process: 79 ExecStart=/usr/sbin/nginx -g daemon on; master_process on; (code=exited, status=0/SUCCESS)
Main PID: 80 (nginx)
Tasks: 3 (limit: 2811)
Memory: 2.2M
CPU: 19ms
CGroup: /system.slice/nginx.service
├─80 "nginx: master process /usr/sbin/nginx -g daemon on; master_process on;"
├─81 "nginx: worker process"
└─82 "nginx: worker process"
Oct 23 13:37:49 webserver systemd[1]: Starting nginx.service - A high performance web server and a reverse proxy server...
Oct 23 13:37:49 webserver systemd[1]: Started nginx.service - A high performance web server and a reverse proxy server.
Starting, stopping, and restarting
The start, stop, restart, and
reload commands change the current state of a service.
sudo systemctl stop nginx systemctl is-active nginx sudo systemctl start nginx sudo systemctl reload nginx sudo systemctl restart nginx systemctl is-active nginx
These commands print nothing on success. reload asks the
service to reread its configuration without stopping; nginx keeps serving
existing connections. Not every service supports it, and
reload-or-restart falls back to a restart when it does not.
restart stops and starts the service, which briefly
interrupts it.
$ sudo systemctl stop nginx $ systemctl is-active nginx inactive $ sudo systemctl start nginx $ sudo systemctl reload nginx $ sudo systemctl restart nginx $ systemctl is-active nginx active
Checking a state in scripts
The is-active, is-enabled, and
is-failed commands print a single word per unit and set the
exit status.
systemctl is-active nginx cron systemctl is-enabled nginx ssh systemctl is-active --quiet nginx && echo "nginx is up"
The exit status is 0 only if all listed units are in the asked state. With
--quiet, nothing is printed, which suits conditions in
scripts. Being active and being enabled are independent: a service can run
without being enabled at boot, and an enabled service can be stopped.
$ systemctl is-active nginx cron active active $ systemctl is-enabled nginx ssh enabled enabled $ systemctl is-active --quiet nginx && echo "nginx is up" nginx is up
Enabling services at boot
Starting a service does not make it start at the next boot. The
enable command does that, and disable reverses
it.
sudo systemctl disable nginx systemctl is-enabled nginx sudo systemctl enable nginx sudo systemctl disable --now cron systemctl is-active cron sudo systemctl enable --now cron
Enabling creates the symbolic links named in the [Install]
section of the unit file; here, a link in
multi-user.target.wants. On Debian, services that also have an
old SysV init script are synchronized with it, which explains the extra
lines. The --now option also starts or stops the service, so
one command does both.
$ sudo systemctl disable nginx Synchronizing state of nginx.service with SysV service script with /lib/systemd/systemd-sysv-install. Executing: /lib/systemd/systemd-sysv-install disable nginx Removed "/etc/systemd/system/multi-user.target.wants/nginx.service". $ systemctl is-enabled nginx disabled $ sudo systemctl enable nginx Synchronizing state of nginx.service with SysV service script with /lib/systemd/systemd-sysv-install. Executing: /lib/systemd/systemd-sysv-install enable nginx Created symlink /etc/systemd/system/multi-user.target.wants/nginx.service → /lib/systemd/system/nginx.service. $ sudo systemctl disable --now cron Synchronizing state of cron.service with SysV service script with /lib/systemd/systemd-sysv-install. Executing: /lib/systemd/systemd-sysv-install disable cron Removed "/etc/systemd/system/multi-user.target.wants/cron.service". $ systemctl is-active cron inactive $ sudo systemctl enable --now cron Synchronizing state of cron.service with SysV service script with /lib/systemd/systemd-sysv-install. Executing: /lib/systemd/systemd-sysv-install enable cron Created symlink /etc/systemd/system/multi-user.target.wants/cron.service → /lib/systemd/system/cron.service.
Listing unit files
The list-unit-files command lists installed unit files with
their enablement state. Unit names or patterns restrict the list.
systemctl list-unit-files nginx.service cron.service ssh.service apt-daily.service systemd-journald.service cryptdisks.service
A static unit has no [Install] section and
cannot be enabled; it is started by other units or by timers, as
apt-daily.service is. A masked unit cannot be
started at all. The PRESET column shows the distribution's
default.
$ systemctl list-unit-files nginx.service cron.service ssh.service apt-daily.service systemd-journald.service cryptdisks.service UNIT FILE STATE PRESET apt-daily.service static - cron.service enabled enabled cryptdisks.service masked enabled nginx.service enabled enabled ssh.service enabled enabled systemd-journald.service static - 6 unit files listed.
Viewing a unit file
The cat command prints a unit file together with all drop-in
files that modify it.
systemctl cat nginx
The [Unit] section holds the description and the ordering
dependencies, [Service] defines how the service is started,
reloaded, and stopped, and [Install] says where the service is
linked when it is enabled. Package unit files live in
/lib/systemd/system; local ones in
/etc/systemd/system take precedence.
$ systemctl cat nginx # /lib/systemd/system/nginx.service # Stop dance for nginx # ======================= # # ExecStop sends SIGQUIT (graceful stop) to the nginx process. # If, after 5s (--retry QUIT/5) nginx is still running, systemd takes control # and sends SIGTERM (fast shutdown) to the main process. # After another 5s (TimeoutStopSec=5), and if nginx is alive, systemd sends # SIGKILL to all the remaining processes in the process group (KillMode=mixed). # # nginx signals reference doc: # http://nginx.org/en/docs/control.html # [Unit] Description=A high performance web server and a reverse proxy server Documentation=man:nginx(8) After=network-online.target remote-fs.target nss-lookup.target Wants=network-online.target [Service] Type=forking PIDFile=/run/nginx.pid ExecStartPre=/usr/sbin/nginx -t -q -g 'daemon on; master_process on;' ExecStart=/usr/sbin/nginx -g 'daemon on; master_process on;' ExecReload=/usr/sbin/nginx -g 'daemon on; master_process on;' -s reload ExecStop=-/sbin/start-stop-daemon --quiet --stop --retry QUIT/5 --pidfile /run/nginx.pid TimeoutStopSec=5 KillMode=mixed [Install] WantedBy=multi-user.target
Creating a service
A program becomes a service with a short unit file. This one runs a script that prints a greeting every ten seconds.
[Unit] Description=Hello demo service After=network.target [Service] ExecStart=/usr/local/bin/hello.sh Restart=on-failure User=jano [Install] WantedBy=multi-user.target
Restart=on-failure restarts the script if it exits with an
error, and User=jano runs it without root privileges. The
WantedBy line makes enable start it at boot.
sudo cp hello.service /etc/systemd/system/ sudo systemctl daemon-reload sudo systemctl enable --now hello systemctl status hello
After adding or changing unit files, daemon-reload makes
systemd read them again. The standard output of the script goes to the
journal, and its lines appear at the bottom of the status.
$ sudo cp hello.service /etc/systemd/system/
$ sudo systemctl daemon-reload
$ sudo systemctl enable --now hello
Created symlink /etc/systemd/system/multi-user.target.wants/hello.service → /etc/systemd/system/hello.service.
$ systemctl status hello
● hello.service - Hello demo service
Loaded: loaded (/etc/systemd/system/hello.service; enabled; preset: enabled)
Active: active (running) since Fri 2026-10-23 13:37:53 CEST; 11s ago
Main PID: 399 (hello.sh)
Tasks: 2 (limit: 2811)
Memory: 576.0K
CPU: 4ms
CGroup: /system.slice/hello.service
├─399 /bin/bash /usr/local/bin/hello.sh
└─402 sleep 10
Oct 23 13:37:53 webserver systemd[1]: Started hello.service - Hello demo service.
Oct 23 13:37:53 webserver hello.sh[399]: Hello number 1
Oct 23 13:38:03 webserver hello.sh[399]: Hello number 2
Overriding settings with a drop-in
Instead of editing a unit file, put changes in a drop-in file in the
unit.d directory. Here, the drop-in sets an environment
variable for the hello service.
[Service] Environment=GREETING=Ahoj
sudo systemctl edit hello opens an editor, creates
/etc/systemd/system/hello.service.d/override.conf, and reloads
systemd when you save. Here, the file is created directly, so
daemon-reload is needed.
sudo mkdir -p /etc/systemd/system/hello.service.d sudo cp override.conf /etc/systemd/system/hello.service.d/ sudo systemctl daemon-reload sudo systemctl restart hello systemctl cat hello journalctl -u hello -n 3 --no-hostname
systemctl cat shows the unit file followed by the drop-in. The
log confirms that the restarted script uses the new greeting. Drop-ins
survive package updates, which replace the files in
/lib/systemd/system.
$ sudo mkdir -p /etc/systemd/system/hello.service.d $ sudo cp override.conf /etc/systemd/system/hello.service.d/ $ sudo systemctl daemon-reload $ sudo systemctl restart hello $ systemctl cat hello # /etc/systemd/system/hello.service [Unit] Description=Hello demo service After=network.target [Service] ExecStart=/usr/local/bin/hello.sh Restart=on-failure User=jano [Install] WantedBy=multi-user.target # /etc/systemd/system/hello.service.d/override.conf [Service] Environment=GREETING=Ahoj $ journalctl -u hello -n 3 --no-hostname Oct 23 13:38:04 systemd[1]: Stopped hello.service - Hello demo service. Oct 23 13:38:04 systemd[1]: Started hello.service - Hello demo service. Oct 23 13:38:04 hello.sh[432]: Ahoj number 1
Failed units
This one-shot service runs a backup script that fails when the backup disk is not mounted.
sudo cp backup.service /etc/systemd/system/ sudo systemctl daemon-reload sudo systemctl start backup systemctl --failed systemctl is-system-running systemctl status backup sudo systemctl reset-failed backup
systemctl start reports the failure and suggests where to
look. systemctl --failed lists all failed units, and the
system state becomes degraded. The status shows the exit code
and, in the journal lines, the error message of the script. After the
problem is fixed or understood, reset-failed clears the failed
state.
$ sudo cp backup.service /etc/systemd/system/
$ sudo systemctl daemon-reload
$ sudo systemctl start backup
Job for backup.service failed because the control process exited with error code.
See "systemctl status backup.service" and "journalctl -xeu backup.service" for details.
$ systemctl --failed
UNIT LOAD ACTIVE SUB DESCRIPTION
● backup.service loaded failed failed Nightly backup
LOAD = Reflects whether the unit definition was properly loaded.
ACTIVE = The high-level unit activation state, i.e. generalization of SUB.
SUB = The low-level unit activation state, values depend on unit type.
1 loaded units listed.
$ systemctl is-system-running
degraded
$ systemctl status backup
× backup.service - Nightly backup
Loaded: loaded (/etc/systemd/system/backup.service; static)
Active: failed (Result: exit-code) since Fri 2026-10-23 13:38:04 CEST; 17ms ago
Process: 462 ExecStart=/usr/local/bin/backup.sh (code=exited, status=1/FAILURE)
Main PID: 462 (code=exited, status=1/FAILURE)
CPU: 3ms
Oct 23 13:38:04 webserver systemd[1]: Starting backup.service - Nightly backup...
Oct 23 13:38:04 webserver backup.sh[462]: backup disk is not mounted
Oct 23 13:38:04 webserver systemd[1]: backup.service: Main process exited, code=exited, status=1/FAILURE
Oct 23 13:38:04 webserver systemd[1]: backup.service: Failed with result 'exit-code'.
Oct 23 13:38:04 webserver systemd[1]: Failed to start backup.service - Nightly backup.
$ sudo systemctl reset-failed backup
Unit properties
The show command prints unit properties in a
key=value form that is easy to process.
systemctl show nginx -p MainPID -p ActiveState -p SubState -p NRestarts systemctl show hello --value -p Environment
The -p option selects properties; without it,
show prints several hundred of them. --value
prints only the value, for example to store it in a shell variable.
NRestarts counts how often systemd restarted the service
automatically.
$ systemctl show nginx -p MainPID -p ActiveState -p SubState -p NRestarts MainPID=133 NRestarts=0 ActiveState=active SubState=running $ systemctl show hello --value -p Environment GREETING=Ahoj
Masking a unit
Disabling a service does not prevent other units or an administrator from starting it. Masking does.
sudo systemctl mask cron sudo systemctl start cron systemctl is-enabled cron sudo systemctl unmask cron
mask links the unit name to /dev/null, so systemd
refuses to start it in any way. Masking is used for services that must not
run, for example a second firewall service that conflicts with the one in
use. unmask removes the link.
$ sudo systemctl mask cron Created symlink /etc/systemd/system/cron.service → /dev/null. $ sudo systemctl start cron Failed to start cron.service: Unit cron.service is masked. $ systemctl is-enabled cron masked $ sudo systemctl unmask cron Removed "/etc/systemd/system/cron.service".
Dependencies
The list-dependencies command shows the units that a unit
pulls in.
systemctl list-dependencies multi-user.target --no-pager | head -n 8
multi-user.target is the normal boot target of a server, and
the enabled services are its dependencies. A filled dot marks an active
unit, and an empty dot an inactive one. The --reverse option
shows which units depend on the given unit.
$ systemctl list-dependencies multi-user.target --no-pager | head -n 8 multi-user.target ● ├─cron.service ● ├─dbus.service ○ ├─e2scrub_reap.service ● ├─hello.service ● ├─nginx.service ● ├─ssh.service ● ├─systemd-ask-password-wall.path
Timers
systemd timers are an alternative to cron jobs.
The list-timers command lists them with their next run time.
systemctl list-timers --all
Each timer activates a service of the same name. The columns show when the
timer fires next, how much time is left, and when it last ran. The
--all option includes inactive timers such as
fstrim.timer, which is not used in this container.
$ systemctl list-timers --all NEXT LEFT LAST PASSED UNIT ACTIVATES Fri 2026-10-23 13:52:45 CEST 14min left - - systemd-tmpfiles-clean.timer systemd-tmpfiles-clean.service Fri 2026-10-23 18:14:20 CEST 4h 36min left - - apt-daily.timer apt-daily.service Sat 2026-10-24 00:00:00 CEST 10h left - - dpkg-db-backup.timer dpkg-db-backup.service Sat 2026-10-24 06:42:07 CEST 17h left - - apt-daily-upgrade.timer apt-daily-upgrade.service Sun 2026-10-25 03:10:21 CET 1 day 14h left - - e2scrub_all.timer e2scrub_all.service - - - - fstrim.timer fstrim.service 6 timers listed.
Service logs
systemctl manages units, while
journalctl reads their logs.
journalctl -u nginx -n 4 --no-hostname
The -u option selects the unit and -n the number
of lines. The log shows the restart from the earlier example. Use
journalctl -u nginx -f to follow new entries.
$ journalctl -u nginx -n 4 --no-hostname Oct 23 13:37:52 systemd[1]: nginx.service: Deactivated successfully. Oct 23 13:37:52 systemd[1]: Stopped nginx.service - A high performance web server and a reverse proxy server. Oct 23 13:37:52 systemd[1]: Starting nginx.service - A high performance web server and a reverse proxy server... Oct 23 13:37:52 systemd[1]: Started nginx.service - A high performance web server and a reverse proxy server.
Best practices for systemctl
- Start with status: Check
systemctl statusandjournalctl -ubefore changing anything. - Use enable --now: It enables and starts a service in one step.
- Use drop-ins: Override packaged units with
systemctl editinstead of editing files in/lib/systemd/system. - Reload after direct edits: Run
daemon-reloadafter changing unit files by hand. - Prefer reload to restart: Reload the configuration when the service supports it, to avoid interruptions.
- Use --user for your own services:
systemctl --usermanages services that run in your user session.
Source
In this article, we have used the systemctl command to inspect
and control services, enable them at boot, create a service and a drop-in
override, handle failed units, and list timers and dependencies.
Author
List all Linux tutorials.