Cheat Sheet

systemctl Commands

systemctl is the command that talks to systemd, the init system on nearly every current Linux distro. This systemd cheat sheet covers the systemctl commands for starting, enabling and inspecting services, the journalctl commands for reading their logs, timers, unit file editing, and reboot and power.

Last updated September 11, 2026

Most state-changing commands need ; reading status and listing units does not. Unit names can drop the suffix ( and are the same).

Manage a Service

CommandWhat it does
Running or not, PID, memory, and the last ten log lines
Same, full lines, no pager (for scripts and copy-paste)
Start it now
Stop it now
Stop then start; drops connections
Reload config without stopping; only for services that support it
Reload if it can, otherwise restart
Restart only if it is already running
Prints or ; exit code 0 when running, for scripts
Prints and exits 0 if it has failed
Send SIGTERM to every process in the unit
Send a different signal
One property, here the main process ID
Several properties
Clear the state (and the start rate limit)
Several units in one command

and differ: sends the service its reload signal (nginx re-reads its config with no dropped connections), kills and relaunches it. exits non-zero when the service is not running, which trips up scripts that only wanted the output.

Enable and Disable

Enabling controls what happens at boot. It does not start anything on its own, and starting does not enable anything.

CommandWhat it does
Start at boot (creates the symlink under )
Start at boot and start it now
Do not start at boot
Remove from boot and stop it now
, , , , or
Make it impossible to start, even by another unit (links it to )
Undo that
Disable then enable; useful after the section changed
Enable or disable according to the distro's preset policy

means the unit has no section and is pulled in by something else; you cannot enable it and do not need to. means someone masked it, on purpose or by a package; restores it.

List Units

CommandWhat it does
Every loaded, active unit (services, sockets, mounts, timers)
Loaded services and their state
Only running services
Include inactive and not-found services
Units that failed
Same thing, shorter
Every installed service file and whether it is enabled
Only enabled ones
Active targets (the systemd version of runlevels)
Socket units and the service each one activates
What nginx pulls in
What depends on nginx
Jobs in progress (usually empty, useful when boot hangs)
Grep the output
, (something failed), , or

shows what systemd has loaded; shows what is installed on disk. A service that is installed but has never started shows up only in the second.

Logs

systemd services log to the journal, and reads it. These are the calls you need alongside systemctl; the journalctl cheat sheet covers the full toolkit.

CommandWhat it does
Every log line from the nginx unit
Follow live, like
Last 100 lines
Same, straight to the terminal
Time window ( also works)
Since midnight
Absolute time
Since the current boot
From the previous boot
Priority and worse (, , , )
ISO timestamps ( for structured output)
Several units interleaved
Recent log with explanations, what tells you to run
Kernel messages only ( equivalent)
How much space the journal takes
Trim it to 500 MB ( by age)
Boot IDs for

shows the last ten lines. When the service failed to start and those lines do not explain why, usually does. If shows nothing for a unit, the service may be writing to its own log file under instead of stdout.

Failed Services

CommandWhat it does
Everything that failed, the first thing to run on a sick box
means at least one unit failed
The failure with systemd's own explanations, what points you to
Only errors from this boot
Why it stopped: , , ,
The process exit code and how it died
How many times it has been restarted
Clear the failed state and the start rate limit
Clear it for every unit
Catch syntax and path errors without loading it
Run the command as a throwaway unit to reproduce the failure

The code on the failure line narrows it down before you read a single log line:

CodeWhat went wrong
is not an absolute path, does not exist, or is not executable
does not exist or the user cannot enter it
The account does not exist on this machine
A sandboxing option (, ) points somewhere invalid
The file is there but has no execute bit
A shell ran the command and could not find it, usually a bad
The program itself exited non-zero; the reason is in its own log output

means either a typo in the name or a new file that systemd has not read yet, so run first. is the rate limit rather than the real error: read the journal for the original crash, fix it, then before starting again.

Timers

Timers are systemd's cron: a unit that starts a matching on a schedule.

CommandWhat it does
Active timers with next and last run times
Include inactive ones
Enable and start a timer (enable the timer, not the service)
Run the job now, outside the schedule
When it fires next
What the last runs logged
Test an expression and see the next run
The next five runs

A timer that runs a script every night at 03:00, in two files:

# /etc/systemd/system/backup.service
[Unit]
Description=Nightly backup

[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup.sh
# /etc/systemd/system/backup.timer
[Unit]
Description=Run backup nightly

[Timer]
OnCalendar=*-*-* 03:00:00
Persistent=true

[Install]
WantedBy=timers.target

runs a missed job at the next boot, which cron never did. Have a crontab line already? The cron to systemd timer converter turns it into these two files, and the cron generator helps with the schedule itself.

Edit Unit Files

Your units go in . Package units live in (or on Debian and Ubuntu, which is the same directory) and get overwritten on upgrade, so never edit those directly. A file in with the same name wins over the one in .

CommandWhat it does
Print the unit file and every drop-in, with their paths
Create or edit a drop-in override in
Copy the whole unit to and edit that
Create a brand new unit from scratch in your editor
Delete your overrides and go back to the package's unit
Re-read every unit file; required after editing one by hand
Every property with its effective value
What will actually run
Where the unit and its overrides live
Check a unit file for errors before loading it
Sandboxing score and which hardening options are missing

opens an empty drop-in in ; whatever you type is layered on top of the original, and it runs for you. It does not restart the service, so follow with . Overriding in a drop-in needs an empty line first, because lines add up:

[Service]
ExecStart=
ExecStart=/usr/sbin/nginx -c /etc/nginx/custom.conf

A minimal service unit for your own program:

[Unit]
Description=My app
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=app
WorkingDirectory=/opt/myapp
ExecStart=/opt/myapp/bin/server --port 3000
Restart=on-failure
RestartSec=5
Environment=NODE_ENV=production

[Install]
WantedBy=multi-user.target

Save it as , then and . The systemd unit generator writes this for you and the systemd unit validator checks one you already have. Moving a Node app off pm2? The pm2 to systemd converter turns an ecosystem file into units.

Remove a Service

CommandWhat it does
Find every file before deleting anything
Stop it and take it out of boot
Delete your own unit
Delete its drop-in overrides too
Make systemd forget it
Clear the leftover entry from
Keep a packaged unit from ever starting, without deleting it

Only delete files under . A unit that came from a package lives in , so deleting it there gets undone by the next upgrade; it, or it if something else keeps pulling it in, and remove the package if you want it gone for good. Skipping leaves a ghost entry that still shows up as failed after the file is gone.

Dependencies and Order

CommandWhat it does
The tree of units nginx pulls in
What would break if nginx did not start
Units that must start before nginx (its chain)
Units that wait for nginx to start first
Everything the normal boot target starts
The directives in effect, after drop-ins are merged
Which units asked for this one
The chain that gated nginx starting, with timings

Ordering and requirement are separate: only says when, and say what has to be pulled in, and a unit with but no can start before its dependency is ready. tolerates the other unit failing, does not, and also stops your unit when the other one goes away. Use with a matching when a service needs a routable address, since only means the stack has been set up.

Boot and Power

CommandWhat it does
Reboot (same as )
Shut down and power off (same as , )
Stop the system without powering off
Sleep to RAM
Sleep to disk (needs swap at least the size of RAM)
Both
The target the system boots into ( or )
Boot to a console, no display manager
Boot to a login screen
Switch to that target now (stops the display manager)
Single-user rescue mode
Emergency shell, root filesystem read-only
How long the last boot took, kernel vs userspace
Every unit sorted by how long it took to start
The chain of units that gated boot
Boot timeline as an SVG

shows time spent, not time that delayed the boot; a unit can take 30 seconds in parallel without slowing anything. shows the ones that actually held things up.

User Services

manages units under your own account, without , from . Handy for a personal sync client, an editor daemon, or a dev server.

CommandWhat it does
Status of a user unit
Enable and start it
Your user services
After editing a file in
Drop-in override for a user unit
Its logs
Keep user services running when you log out, and start them at boot

Without , user services stop when your last session closes, which is the usual reason a service dies as soon as you disconnect from SSH.

service and chkconfig

The old SysV commands still exist on most distros and forward to systemd, so they work but hide what is happening and drop the useful output.

Old commandsystemctl equivalent
for the boot target, for the current one

is not , which reads and writes kernel parameters and has nothing to do with services.

Gotchas

  • is now, is at boot. A service you enabled but never started is still stopped until you reboot; does both.
  • After editing any unit file by hand, run , or systemd keeps using the old version and warns . reloads for you but does not restart.
  • A drop-in that sets needs on its own line first to clear the original, or the unit fails with .
  • is the start rate limit, not the real error. Read for the crash that caused it, fix that, then before starting again.
  • means someone ran , or the package masks it by design. first, then .
  • truncates long lines and pages its output. Add when you want to copy from it or pipe it.
  • means no systemd: most Docker containers, macOS, Alpine, and WSL without in . Inside a container, run the process directly and let the container's restart policy handle failures; the docker commands sheet covers that side.
  • needs an absolute path and does not understand shell syntax. fails; use and , or call explicitly.

systemctl FAQ

What is the difference between systemctl start and systemctl enable?

start runs the service now and does nothing about the next boot. enable does the opposite: it creates the symlink under /etc/systemd/system that makes the service start at boot, but does not start it now. A freshly installed service that you only enabled is still stopped until you start it or reboot, and a service you only started is gone after a reboot. systemctl enable --now nginx does both in one step, and disable --now stops it and removes it from boot. Check either state with systemctl is-active nginx and systemctl is-enabled nginx.

How do I list all running services with systemctl?

systemctl list-units --type=service --state=running shows only services that are currently running, one per line with their description. Drop --state=running to include loaded services that are inactive or failed, add --all to include ones that never loaded, and use --state=failed (or the shortcut systemctl --failed) for the ones that crashed. list-units shows what systemd has in memory; list-unit-files --type=service shows every installed service file and whether it is enabled, disabled, static or masked, which is the list to read when you want to know what will start at boot. Add --no-pager when you are piping into grep.

Why does systemctl say command not found?

The machine is not running systemd. That is the case inside most Docker containers, which run a single process rather than an init system, so start the app directly or use the container's restart policy instead. It is also true on macOS, which uses launchctl, on Alpine and Devuan, which use OpenRC and sysvinit, on WSL 1 and on WSL 2 unless systemd=true is set in /etc/wsl.conf, and on very old CentOS 6 and Ubuntu 14.04 hosts, where the equivalent is service nginx start and chkconfig or update-rc.d. If systemctl exists but every call fails with Failed to connect to bus, you are in a chroot or container with systemd installed but not running as PID 1.

What does systemctl daemon-reload do?

It makes systemd re-read every unit file on disk, re-run the unit generators, and rebuild its dependency graph in memory. It starts, stops and restarts nothing, so it is safe to run on a busy production host, and a service that is already running keeps the settings it started with until you restart it. Run it after you create, edit or delete a unit file by hand; you do not need it after systemctl edit, which reloads for you, or after a package install, which does it in its own post-install script. If you skip it, systemd keeps using the cached copy and prints Warning: The unit file, source configuration file or drop-ins of nginx.service changed on disk. The related daemon-reexec is a different thing: it re-executes the systemd binary itself, which is only for after a systemd package upgrade.

Where are systemctl service files stored?

Three directories, in falling order of precedence: /run/systemd/system for transient units, /etc/systemd/system for yours and anything you overrode, and /usr/lib/systemd/system for the ones packages ship (/lib/systemd/system on Debian and Ubuntu is the same directory through a symlink). A file in /etc with the same name completely replaces the packaged one, which is why local edits belong there and never in /usr/lib. Drop-in overrides sit in a nginx.service.d directory next to the unit and are merged on top rather than replacing it. User units live in ~/.config/systemd/user. To find which file a running unit actually came from, run systemctl show nginx -p FragmentPath,DropInPaths, or systemctl cat nginx to print the contents of all of them in merge order.

Related cheat sheets