systemd Cheatsheet

systemctl Basics

Use this systemd reference while you build software engineering projects, review code, or refresh the syntax you reach for most.

Looking at State

systemctl with no arguments lists every unit systemd currently has in memory. In practice you always narrow it.

CommandShows
systemctl status nginxState, main PID, cgroup, last 10 log lines
systemctl statusWhole-system state and the unit tree
systemctl is-active nginxactive / inactive, exit code 0 when active
systemctl is-enabled nginxenabled / disabled / masked / static
systemctl is-failed nginxfailed, exit 0 when the unit failed
systemctl list-units --type=serviceLoaded services
systemctl list-units --state=failedEverything broken right now
systemctl --failedShorthand for the line above
systemctl list-unit-filesInstalled unit files and their enablement
systemctl list-dependencies nginxRecursive dependency tree
systemctl list-timers --allTimers with next and last elapse
systemctl list-socketsSocket units by listening address
systemctl show nginxEvery resolved property, machine readable

The .service suffix is optional in every command. systemctl status ngin* accepts globs.

Start, Stop, Restart, Reload

systemctl start nginx
systemctl stop nginx
systemctl restart nginx           # stop then start, drops connections
systemctl reload nginx            # only if the unit defines ExecReload=
systemctl reload-or-restart nginx # reload when supported, else restart
systemctl try-restart nginx       # restart only if already running
systemctl kill nginx              # send SIGTERM to the cgroup
systemctl kill -s SIGKILL nginx   # or a specific signal

reload fails outright when the unit file has no ExecReload=. reload-or-restart is the safe scripted choice. All of these block until the job finishes unless you pass --no-block.

Enable and Disable

enable is about boot, start is about now. They are independent, and forgetting that is the most common systemd surprise.

systemctl enable nginx            # create the [Install] symlinks
systemctl enable --now nginx      # enable and start in one step
systemctl disable --now nginx     # disable and stop
systemctl reenable nginx          # remove then recreate the symlinks
systemctl preset nginx            # reset to the distro preset policy

enable only works when the unit has an [Install] section. Units without one report static, which means they are pulled in by another unit rather than enabled directly.

daemon-reload vs restart vs reload

Three different things that people mix up constantly.

CommandEffect
systemctl daemon-reloadRe-read unit files from disk into systemd
systemctl restart fooStop and start the foo process
systemctl reload fooAsk the foo process to re-read its own config

Edit a unit file, then daemon-reload, then restart. Without the reload systemd keeps running the old unit definition and your change silently does nothing. systemctl status warns with "changed on disk" when you forget.

systemctl daemon-reexec re-executes the systemd manager itself, serializing and restoring state. You need it after a systemd package upgrade, almost never otherwise.

Masking, Linking, Reverting

systemctl mask apache2      # symlink the unit to /dev/null, unstartable
systemctl unmask apache2
systemctl link /opt/app/app.service   # pull an out-of-tree file into the path
systemctl revert nginx      # delete drop-ins and local overrides
systemctl set-property nginx MemoryMax=1G          # persistent
systemctl set-property --runtime nginx CPUQuota=50% # until reboot

mask is stronger than disable. A disabled unit still starts when another unit pulls it in as a dependency, a masked one cannot start at all. revert throws away everything under /etc/systemd/system/foo.service.d/ and any /etc copy of the file, returning you to the packaged version.

Scoping and Remote Hosts

Every command above takes a manager scope. The default is --system.

systemctl --user status syncthing     # your per-user manager
systemctl --global enable foo.service # default for all future users
systemctl -H deploy@web1 status nginx # over SSH
systemctl -M mycontainer list-units   # inside a machined container
systemctl --no-pager --plain list-units --type=timer

--no-pager and --plain matter in scripts, because interactive output is paged and decorated with tree glyphs by default. SYSTEMD_COLORS=0 strips ANSI codes.