Skip to content

Managing Services


systemctl is the single command responsible for controlling nearly everything systemd manages — starting and stopping services, checking their status, and controlling whether they start automatically at boot. This chapter covers it hands-on, including a distinction that catches nearly everyone off guard the first time: starting a service and making it start automatically on boot are two completely separate actions.

Checking A Service’s Status

systemctl status ssh
● ssh.service - OpenBSD Secure Shell server
     Loaded: loaded (/lib/systemd/system/ssh.service; enabled; vendor preset: enabled)
     Active: active (running) since Thu 2026-01-15 09:14:22 UTC; 3h 12min ago
   Main PID: 734 (sshd)
      Tasks: 1 (limit: 4617)
     Memory: 4.2M
        CPU: 89ms
     CGroup: /system.slice/ssh.service
             └─734 /usr/sbin/sshd -D

Jan 15 09:14:22 hostname systemd[1]: Starting OpenBSD Secure Shell server...
Jan 15 09:14:22 hostname systemd[1]: Started OpenBSD Secure Shell server.

A few things worth reading carefully here:

  • The colored dot at the top () is a quick visual health indicator — green generally means active and healthy, red means failed.
  • Loaded shows which unit file is actually in use, and whether it’s currently enabled (starts on boot) or disabled.
  • Active shows the current runtime state — active (running) for something actively executing, inactive (dead) for something stopped, or failed if it tried to start and couldn’t.
  • Main PID ties directly back to the PID/process vocabulary — this is the actual process systemd is tracking as “the service,” and it’s a real PID you could look up with ps like any other.
  • The last few lines are recent log entries for this specific unit — a preview of what journalctl -u covers in full later in this section.

Starting, Stopping, And Restarting

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

Straightforward — these affect the service’s current running state only, right now, with no effect on what happens at the next boot.

There’s a fourth option worth knowing specifically:

sudo systemctl reload nginx

reload asks a service to re-read its configuration without fully stopping and restarting it — meaningfully different from restart for something like a web server, where a full restart would briefly drop active connections, while a reload can often apply new configuration without any interruption at all. Not every service supports this cleanly; some fall back to a full restart internally even when asked to reload, depending on how their unit file defines the behavior.

The Distinction That Catches Everyone: start vs. enable

This is worth its own heading because it’s genuinely the most common point of confusion for anyone new to systemd.

sudo systemctl start nginx

This starts nginx right now. It does nothing about what happens the next time the system boots — reboot immediately afterward, and nginx will not be running, because nothing told systemd it should start automatically.

sudo systemctl enable nginx

This does the opposite: it configures nginx to start automatically on every future boot, but — and this is the part that trips people up — it does not start nginx right now. Run only enable and check systemctl status nginx immediately afterward, and you’ll see it’s still inactive.

    flowchart LR
    A["systemctl start"] --> B["Running now.<br/>Nothing changes for next boot."]
    C["systemctl enable"] --> D["Will start on next boot.<br/>Not running right now."]
    E["systemctl enable --now"] --> F["Both: running now,<br/>AND starts on future boots."]
  

For the common case of “I want this running now, and I want it to stay that way after every reboot,” combine both with --now:

sudo systemctl enable --now nginx

The reverse pair works identically: disable prevents future automatic starts without stopping anything currently running; disable --now does both.

How enable Actually Works

Under the hood, enable doesn’t modify the service’s own unit file at all — it creates a symlink from the unit file into the appropriate target’s dependency directory, which is exactly how that target ends up knowing to start this service when it’s reached. disable simply removes that symlink. This is worth knowing mainly because it explains why enable/disable are near-instant, lightweight operations — they’re not editing configuration, just adding or removing a pointer.

A Stronger Form Of Disable: mask

sudo systemctl mask nginx

disable stops a service from starting automatically, but it can still be started manually, or as a dependency of something else. mask goes further — it makes the unit completely unstartable, by anyone, until explicitly unmasked, by linking the unit file to /dev/null (recall /dev/null from earlier in this course as the file that discards anything written to it — here it’s being used slightly differently, as a target systemd recognizes as “this unit is intentionally blocked”). This is the right tool specifically when you need to guarantee a service absolutely cannot start under any circumstance, including as a side-effect dependency of something else starting it.

sudo systemctl unmask nginx

Reverses it, returning the unit to its normal, startable state.

Quick Status Checks For Scripts

Three commands return a simple yes/no answer via their exit code, rather than printing detailed status — genuinely useful inside scripts that need to make a decision based on a service’s state, rather than parsing status output by hand:

systemctl is-active nginx
systemctl is-enabled nginx
systemctl is-failed nginx

Each prints a short word (active, enabled, failed, or their opposites) and, importantly, sets an exit code a script can check directly, rather than needing to grep through the fuller status output for the same information.

After Editing A Unit File Directly: daemon-reload

If you ever edit a unit file directly — covered properly in the next chapter — systemd doesn’t notice the change automatically. It keeps its own in-memory copy of every unit’s configuration, loaded at startup, and editing the file on disk doesn’t refresh that copy on its own:

sudo systemctl daemon-reload

This tells systemd to re-read all unit files from disk. Skipping this step after an edit is a common source of “I changed the config but nothing’s different” confusion — the running service is still working off the old, cached definition until daemon-reload runs.

Quick Reference

CommandEffect
start / stop / restartChange current running state only
reloadRe-read config without a full restart, where supported
enable / disableChange boot-time behavior only, not current state
enable --now / disable --nowBoth at once
mask / unmaskBlock or unblock a unit from starting at all
statusDetailed current state, recent logs
is-active / is-enabled / is-failedQuick, script-friendly boolean checks
daemon-reloadReload systemd’s cache after editing a unit file

What’s Next

You can now fully control any existing service. The next chapter goes one level deeper — the actual structure of a unit file itself, reading one properly and writing a basic one from scratch.

Last updated on