systemd and journalctl Cheat Sheet

systemd quick reference for admins: systemctl commands, journalctl filters, unit files and drop-ins, writing a service and a timer, boot analysis and per-distribution naming.

Start here

Is it running
systemctl status nginx
Why did it stop
journalctl -u nginx -n 50 -x
What is broken right now
systemctl --failed
Start it and keep it after reboot
systemctl enable --now nginx
I edited a unit file
systemctl daemon-reload
Why is boot slow
systemd-analyze blame
Two words that are not the same. Active means running now. Enabled means it starts at boot. A service can be active and disabled, which is why it disappears after the next reboot, and that is the single most common systemd surprise for a Windows admin.

Controlling units

TaskCommand
Status, with the last log linessystemctl status sshd
Start, stop, restartsystemctl start|stop|restart sshd
Reload configuration without dropping connectionssystemctl reload nginx
Reload if the unit supports it, otherwise restartsystemctl reload-or-restart nginx
Enable at boot and start nowsystemctl enable --now sshd
Disable at boot and stop nowsystemctl disable --now sshd
Quick yes or no answers, useful in scriptssystemctl is-active sshd, systemctl is-enabled sshd
Make it impossible to start, even as a dependencysystemctl mask sshd
Undo thatsystemctl unmask sshd
Clear the failed state after fixing somethingsystemctl reset-failed sshd
disable is not stop. systemctl disable only removes the boot symlink, leaving the service running until the next reboot. Use --now when you mean both, which is almost always.

Finding things

QuestionCommand
Services loaded right nowsystemctl list-units --type=service
Only the running onessystemctl list-units --type=service --state=running
Everything installed, running or notsystemctl list-unit-files --type=service
What is enabled at bootsystemctl list-unit-files --state=enabled
I do not know the exact namesystemctl list-units --type=service | grep -i ssh
Where is this unit’s filesystemctl show -p FragmentPath sshd
Show the unit file and its drop-inssystemctl cat sshd
What does this unit depend onsystemctl list-dependencies sshd
Every property systemd knows about itsystemctl show sshd

journalctl

TaskCommand
Last 50 lines for one servicejournalctl -u nginx -n 50
Follow livejournalctl -u nginx -f
Errors and worse, system widejournalctl -p err -b
This boot onlyjournalctl -b
The previous boot, for a crashjournalctl -b -1
Which boots are recordedjournalctl --list-boots
A time windowjournalctl --since "2026-09-16 08:00" --until "09:00"
Relative timejournalctl --since "1 hour ago"
Kernel messagesjournalctl -k
Add explanations where they existjournalctl -xe
Structured output for parsingjournalctl -u nginx -o json-pretty
How much disk the journal usesjournalctl --disk-usage
Trim itjournalctl --vacuum-size=500M or --vacuum-time=14d
PriorityLevel
0 to 2emerg, alert, crit
3err
4warning
5 to 7notice, info, debug
The journal may not survive a reboot. With Storage=auto, which is the common default, logs are kept on disk only if /var/log/journal exists. If journalctl -b -1 returns nothing after a crash, create that directory and restart systemd-journald, then you will have history next time.

Unit files

LocationMeaning
/usr/lib/systemd/systemShipped by packages. Do not edit, an update overwrites it.
/lib/systemd/systemSame thing on the Debian family, where it is a symlink to the above
/etc/systemd/systemYour overrides. Wins over the package version.
/run/systemd/systemRuntime units, gone after reboot
/etc/systemd/system/name.service.d/Drop-in directory: small files that change part of a unit
TaskCommand
Change a setting safely, creating a drop-insystemctl edit nginx
Copy the whole unit and edit thatsystemctl edit --full nginx
Throw away your changessystemctl revert nginx
See the effective unit, drop-ins includedsystemctl cat nginx
After editing any file by handsystemctl daemon-reload
Check a unit file for mistakessystemd-analyze verify /etc/systemd/system/my.service
Forgetting daemon-reload is the classic time sink. systemd keeps units in memory, so an edited file changes nothing until it is reloaded, and systemctl restart happily starts the old definition. systemctl edit does the reload for you, which is the better reason to use it.

A service of your own

A script that must run as a managed service. Save as /etc/systemd/system/report.service, then systemctl daemon-reload and systemctl enable --now report.

[Unit]
Description=Nightly report job
After=network-online.target
Wants=network-online.target

[Service]
Type=oneshot
ExecStart=/usr/local/bin/report.sh
User=svc-report
WorkingDirectory=/opt/report

[Install]
WantedBy=multi-user.target
DirectiveWhat it controls
Type=simpleDefault. The process started by ExecStart is the service.
Type=oneshotRuns, finishes, and that is success. Right for scripts.
Type=forkingThe program daemonises itself. Usually needs PIDFile=.
Type=notifyThe program tells systemd when it is ready
Restart=on-failureRestart after a non-zero exit. Also always, no.
RestartSec=10Wait before restarting
User=, Group=Run as a service account, not root
Environment=Set a variable, or use EnvironmentFile=
After=, Wants=Ordering and a soft dependency
WantedBy=multi-user.targetWhat enable hooks it into
The PATH is not your PATH. A unit runs with a minimal environment and no shell profile, so use absolute paths in ExecStart and inside the script. This is the same trap as a PowerShell script that works by hand and fails in Task Scheduler.

Timers instead of cron

A timer is the scheduled task. It has the same name as the service it starts, with a .timer extension.

[Unit]
Description=Run the nightly report

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

[Install]
WantedBy=timers.target
TaskCommand or value
Enable the timer, not the servicesystemctl enable --now report.timer
What is scheduled and when it next runssystemctl list-timers --all
Test the schedule expression firstsystemd-analyze calendar "Mon *-*-* 06:30:00"
Run the job now, without waitingsystemctl start report.service
Did it workjournalctl -u report.service -n 30
Every day at 02:00OnCalendar=*-*-* 02:00:00
Every Monday at 06:30OnCalendar=Mon *-*-* 06:30:00
Every 15 minutesOnCalendar=*:0/15
Catch up after the machine was offPersistent=true
Spread load across a fleetRandomizedDelaySec=300
Why timers beat cron here. The output lands in the journal instead of a mail spool, the job inherits the unit’s user and environment, Persistent=true handles a missed run, and list-timers answers “what runs on this box” in one line. cron still works and is fine for something trivial.

Boot, targets and timing

TaskCommand
How long did the last boot takesystemd-analyze time
What took the longestsystemd-analyze blame
What actually delayed the chainsystemd-analyze critical-chain
Current default targetsystemctl get-default
Boot to console instead of a desktopsystemctl set-default multi-user.target
Switch target nowsystemctl isolate multi-user.target
Reboot and power offsystemctl reboot, systemctl poweroff
TargetWindows equivalent, roughly
multi-user.targetServer Core: full system, no graphical session
graphical.targetDesktop Experience
rescue.targetSafe mode, single user
emergency.targetBarely anything mounted, for repair
blame lists the slowest units, not the cause. A unit can be slow because it waited for something else. critical-chain shows the ordering, which is what you need when boot takes four minutes and the culprit is a network mount that nobody can reach.

Distribution notes

DetailWhere it differs
SSH unit namesshd on the RHEL family and Photon OS, ssh on Debian and Ubuntu
Web server unit namehttpd on the RHEL family, apache2 on Debian and Ubuntu
Time sync unitchronyd on the RHEL family, systemd-timesyncd or chrony on Ubuntu
Firewall unitfirewalld on the RHEL family, ufw on Ubuntu
Plain log files, if you prefer them/var/log/messages on the RHEL family, /var/log/syslog on Debian and Ubuntu
Journal persistence by defaultUsually on with the RHEL family, often volatile on minimal Debian and appliance images
vCenter Server AppliancePhoton OS, systemd throughout. service-control --status --all is the VMware wrapper around the same units.
ESXiNo systemd at all. Services are /etc/init.d/hostd restart and friends.
Very old systemsRHEL 6 and Ubuntu 14.04 predate systemd: use service name status and chkconfig.

FAQ

The service starts by hand and dies at boot.
Usually a dependency that is not ready yet, most often the network or a mount. Add After=network-online.target together with Wants=network-online.target, and for a mounted path add RequiresMountsFor=. journalctl -b -u name shows the difference between the two attempts.
systemctl status shows active, but the application is not working.
With Type=simple, systemd reports active as soon as the process starts, not when it is ready to serve. That is what Type=notify exists for. Until then, check the application’s own log rather than trusting the unit state.
My change to the unit file does nothing.
Either you edited the packaged copy under /usr/lib/systemd/system while an override in /etc/systemd/system takes precedence, or you skipped systemctl daemon-reload. systemctl cat name shows what systemd is actually using.
A service keeps restarting in a loop.
Restart=always with a program that exits immediately. systemd applies a rate limit and then gives up, leaving the unit failed. Fix the program, or set StartLimitIntervalSec and StartLimitBurst deliberately, and clear the state with systemctl reset-failed.
How do I see everything that happened around a crash?
journalctl -b -1 -p err for errors in the previous boot, then widen with a time window around the timestamp. If the previous boot is not there, the journal is volatile on this machine, and creating /var/log/journal fixes that for next time.