Skip to content

systemctl

systemctl is the command-line client of systemd: it starts, stops, enables and inspects units, and its status output is the first thing to read when a service misbehaves. Knowing the difference between active and enabled, and reading a failed status line such as status=203/EXEC, covers most service questions in interviews.

Track: Core · Interview weight: High


Must-Know Facts

Fact Value Verify with
start / stop / restart Change the running state now systemctl is-active <unit>
reload Ask the service to reread its configuration (ExecReload=); the main PID stays systemctl show -p MainPID
enable / disable Create or remove [Install] symlinks; affects the next boot only systemctl is-enabled <unit>
enable --now Enable and start in one command systemctl status <unit>
mask / unmask Link the unit to /dev/null so nothing can start it systemctl is-enabled shows masked
is-active exit codes 0 active, 3 inactive or failed systemctl is-active <unit>; echo $?
status exit codes 0 active, 3 not running, 4 no such unit systemctl status <unit>; echo $?
Enablement states enabled, disabled, static (no [Install]), masked, alias, indirect systemctl list-unit-files
Preset Vendor default for enable: RHEL disables most new services, Ubuntu enables and starts them on install systemctl list-unit-files <unit>
Failed units systemctl --failed; clear with systemctl reset-failed systemctl is-failed <unit>
Reading config systemctl cat <unit> prints the unit and its drop-ins systemctl cat sshd
Properties systemctl show <unit> -p MainPID -p Restart -p NRestarts systemctl show <unit>
After editing units systemctl daemon-reload Warning "changed on disk"
Without root Read commands work; changes need sudo ("Interactive authentication required") systemctl start <unit> as a user
User units systemctl --user manages the per-user manager systemctl --user status

Start, Enable, Status

start affects the running system and enable affects the next boot; the two are independent. enable --now does both.

sudo systemctl stop nginx; sudo systemctl disable nginx
systemctl is-active nginx; echo rc=$?; systemctl is-enabled nginx; echo rc=$?
systemctl start nginx
sudo systemctl enable --now nginx

Output:

inactive
rc=3
disabled
rc=1
Failed to start nginx.service: Interactive authentication required.
See system logs and 'systemctl status nginx.service' for details.
Created symlink '/etc/systemd/system/multi-user.target.wants/nginx.service' → '/usr/lib/systemd/system/nginx.service'.

The symlink is what enable does: WantedBy=multi-user.target in the unit's [Install] section becomes a link in multi-user.target.wants/.

Reading status

systemctl status nginx --no-pager -n 3

Output:

● nginx.service - The nginx HTTP and reverse proxy server
     Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; preset: disabled)
     Active: active (running) since Wed 2026-09-16 19:10:57 UTC; 7ms ago
 Invocation: 22117ace13564a3a838c4206f09ea275
    Process: 3609 ExecStartPre=/usr/bin/rm -f /run/nginx.pid (code=exited, status=0/SUCCESS)
    Process: 3611 ExecStartPre=/usr/sbin/nginx -t (code=exited, status=0/SUCCESS)
    Process: 3615 ExecStart=/usr/sbin/nginx (code=exited, status=0/SUCCESS)
   Main PID: 3616 (nginx)
      Tasks: 5 (limit: 51276)
     Memory: 4.7M (peak: 4.7M)
        CPU: 23ms
     CGroup: /system.slice/nginx.service
             ├─3616 "nginx: master process /usr/sbin/nginx"
             ├─3617 "nginx: worker process"
             ├─3618 "nginx: worker process"
             ├─3620 "nginx: worker process"
             └─3621 "nginx: worker process"

Sep 16 19:10:56 rocky-01 nginx[3611]: nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
Sep 16 19:10:56 rocky-01 nginx[3611]: nginx: configuration file /etc/nginx/nginx.conf test is successful
Sep 16 19:10:57 rocky-01 systemd[1]: Started nginx.service - The nginx HTTP and reverse proxy server.
Line Meaning
/ / × Active / inactive / failed
Loaded: Unit file path; enablement; vendor preset
Active: State (sub-state) and since when
Process: Helper commands (ExecStartPre=, ExecStart= of a forking service) and their exit status
Main PID: The process systemd tracks as the service
Tasks: / Memory: / CPU: cgroup accounting, with limits in parentheses
CGroup: Every process of the service
Last lines Recent journal entries for the unit (-n sets how many)

Scriptable checks

systemctl is-active nginx; systemctl is-enabled nginx; systemctl is-failed nginx; echo rc=$?
systemctl status nosuch.service; echo rc=$?
systemctl show nginx -p MainPID -p ActiveState -p SubState -p ExecMainStartTimestamp -p NRestarts -p UnitFileState

Output:

active
enabled
active
rc=1
Unit nosuch.service could not be found.
rc=4
MainPID=3616
NRestarts=0
ExecMainStartTimestamp=Wed 2026-09-16 19:10:57 UTC
ActiveState=active
SubState=running
UnitFileState=enabled

is-failed returns 0 only for a failed unit, so its exit status was 1 here. systemctl show prints the properties in its own order, not in the order requested.


Reload vs Restart

reload runs ExecReload= and keeps the process; restart stops and starts it, which drops connections and gives it a new PID.

sudo systemctl reload nginx; systemctl show nginx -p MainPID
sudo systemctl restart nginx; systemctl show nginx -p MainPID

Output:

MainPID=3616
MainPID=3650
reload restart try-restart reload-or-restart
Process Kept Replaced Replaced if running Kept if reload is supported
Connections Kept Dropped Dropped Depends
Stopped unit Error Started Left stopped Started

Validate configuration before a reload

A reload with a broken configuration can leave a service on the old settings or stop it. Run the service's own check first (nginx -t, sshd -t, apachectl configtest, named-checkconf), as the nginx unit does in ExecStartPre=.


Mask

mask links the unit name to /dev/null in /etc/systemd/system, which blocks manual starts and dependencies alike. It keeps a conflicting service (for example firewalld when nftables is managed directly) from coming back.

sudo systemctl mask nginx
sudo systemctl start nginx
systemctl is-enabled nginx; systemctl status nginx --no-pager | head -3
sudo systemctl unmask nginx; systemctl is-enabled nginx

Output:

Created symlink '/etc/systemd/system/nginx.service' → '/dev/null'.
Failed to start nginx.service: Unit nginx.service is masked.
masked
● nginx.service
     Loaded: masked (Reason: Unit nginx.service is masked.)
     Active: active (running) since Wed 2026-09-16 19:10:57 UTC; 195ms ago
Removed '/etc/systemd/system/nginx.service'.
enabled

mask does not stop a running service

The status above still shows active (running). systemctl mask --now masks the unit and stops it in one step.


Listing Units

systemctl list-unit-files nginx.service crond.service sshd.service
systemctl list-units --type=service --state=failed --no-legend
systemctl list-units "sys*" --type=service --no-legend | head -4

Output:

UNIT FILE     STATE    PRESET
crond.service enabled  enabled
nginx.service enabled  disabled
sshd.service  disabled enabled

3 unit files listed.
● systemd-network-generator.service loaded failed failed Generate network units from Kernel command line
  systemd-hostnamed.service                loaded active running Hostname Service
  systemd-journal-flush.service            loaded active exited  Flush Journal to Persistent Storage
  systemd-journald.service                 loaded active running Journal Service
  systemd-logind.service                   loaded active running User Login Management
Command Lists
systemctl list-units Units loaded in memory (active by default; --all for all)
systemctl list-unit-files Unit files on disk with their enablement and preset
systemctl --failed Failed units
systemctl list-dependencies <unit> What a unit pulls in; --reverse for what pulls it in
systemctl list-jobs Queued start and stop jobs, useful when boot hangs
systemctl list-timers Timers and their next run

sshd.service shows disabled with preset enabled because this playground starts SSH through sshd.socket; a default RHEL install enables sshd.service.


Distribution Differences

The unit commands are identical; package defaults and service names differ.

sudo dnf install -y memcached >/dev/null 2>&1
systemctl is-enabled memcached; systemctl is-active memcached

Output:

disabled
inactive

RHEL's preset (/usr/lib/systemd/system-preset/99-default-disable.preset contains disable *) leaves new services disabled and stopped; the administrator enables them.

sudo DEBIAN_FRONTEND=noninteractive apt-get install -y memcached 2>&1 | grep -iE 'symlink|memcached.service'
systemctl is-enabled memcached; systemctl is-active memcached
ss -tlnp | grep 11211

Output:

Created symlink /etc/systemd/system/multi-user.target.wants/memcached.service → /usr/lib/systemd/system/memcached.service.
enabled
active
LISTEN 0      1024       127.0.0.1:11211      0.0.0.0:*          
LISTEN 0      1024           [::1]:11211         [::]:*          

Debian packages enable and start their services during installation, so a new daemon listens before it is configured. /usr/sbin/policy-rc.d returning 101 blocks this in images and chroots.

Service RHEL / Rocky Ubuntu / Debian
SSH server sshd.service ssh.service, ssh.socket (socket-activated since 22.10)
Cron crond.service cron.service
Apache httpd.service apache2.service
Firewall firewalld.service ufw.service
Network NetworkManager.service systemd-networkd.service (server), NetworkManager (desktop)
Time sync chronyd.service systemd-timesyncd.service or chrony.service

On Ubuntu 24.04:

systemctl status sshd --no-pager | head -3

Output:

Unit sshd.service could not be found.

On Ubuntu 24.04 the sshd alias exists only while ssh.service is enabled; with socket activation it is not created, so use the real name ssh.


Common Errors

Failed to start nginx.service: Unit nginx.service is masked.

Cause: the unit is linked to /dev/null.

Fix: sudo systemctl unmask nginx, then start it; check why it was masked first.

Failed to start nginx.service: Interactive authentication required.

Cause: a state change ran without root and no polkit agent could ask for a password.

Fix: sudo systemctl start nginx.

Unit nosuch.service could not be found.

Cause: wrong name, the package is not installed, or a new unit file was added without daemon-reload.

Fix: systemctl list-unit-files | grep <name>, then sudo systemctl daemon-reload.


Interview Checkpoints

L1: What is the difference between systemctl enable and systemctl start?

Say first: start runs the service now; enable creates the symlinks that start it at boot. Neither implies the other; enable --now does both.

Proof: after enable, is-enabled says enabled while is-active can still say inactive.

Follow-up: What does enable create on disk?

L1: What is the difference between reload and restart?

Say first: reload tells the running process to reread its configuration and keeps its PID and connections; restart stops and starts it.

Proof: systemctl show -p MainPID nginx stays the same after reload and changes after restart.

Follow-up: What happens on reload for a unit without ExecReload=?

L1: What does mask do, and how is it different from disable?

Say first: disable removes boot links, but the unit can still be started manually or as a dependency; mask links it to /dev/null so nothing can start it.

Proof: systemctl start on a masked unit fails with Unit ... is masked.

Follow-up: Give a case where masking is the right choice.

L2: Make nginx start at boot and start it now, then confirm both.

Say first: enable with --now and check both states.

Proof: sudo systemctl enable --now nginx && systemctl is-enabled nginx && systemctl is-active nginx

Follow-up: What exit code does is-active return for a stopped unit?

L2: List every failed unit and clear the list after fixing them.

Say first: use --failed, then reset-failed.

Proof: systemctl --failed, systemctl status <unit>, sudo systemctl reset-failed

Follow-up: Why does a unit stay in the failed list after the underlying problem is fixed?

L2: Print the main PID and restart count of a service for a monitoring script.

Say first: use systemctl show with --value.

Proof: systemctl show -p MainPID --value nginx; systemctl show -p NRestarts --value nginx

Follow-up: Why is show better than parsing status?

L3: A package was installed on Ubuntu and a new port is already listening before configuration.

Say first: Debian packages enable and start services on install; check the unit and decide whether to stop and disable it until it is configured.

Proof: ss -tlnp, systemctl status <unit>, then sudo systemctl disable --now <unit>

Follow-up: How do you prevent it in a Docker build or golden image? (policy-rc.d.)

L3: systemctl status shows active (running), but the application does not respond.

Say first: systemd only knows the process exists; check what it is doing and what it logs.

Proof: journalctl -u <unit> -n 50, ss -tlnp for the listening port, ps -o stat,wchan -p <MainPID> for a blocked or stopped process, then the application's own health endpoint.

Follow-up: Which unit type lets systemd know the application is ready? (Type=notify.)


Captured on Rocky Linux 10.2 and Ubuntu 24.04.4 LTS (iximiuz Labs microVMs, kernel 6.1.167), 2026-09.