systemd & journalctl Cheat Sheet
Every Linux SRE rebuilds this list in their head three times before it sticks. One page, the commands you actually run, no man spelunking.
Service status & lifecycle
Five verbs cover 99% of what you do at the prompt. The sixth, is-active, is the one you script.
systemctl status nginx, current state plus the last 10 log lines. The default first move.systemctl start | stop | restart nginx, obvious.restartkills + restarts; not the same asreload.systemctl enable --now nginx, start now and at boot, in one command.disable --nowfor the reverse.systemctl is-active nginx, exits 0 if running. The script-friendly check.is-enabledfor boot state.systemctl list-units --failed, what's broken right now. Run it after every reboot.systemctl list-units --type=service --state=running, everything actually running.--allincludes inactive.
journalctl, scoping logs
Journals on a busy box have millions of lines. Without scoping you're reading the whole novel; with it, you're on the page that matters.
journalctl -u nginx, just nginx. Use this 90% of the time.journalctl -u nginx -u php-fpm, multiple units. Repeat-u; don't comma-separate.journalctl -u nginx -p warning, warning and above. Levels:emerg,alert,crit,err,warning,notice,info,debug.journalctl -u nginx -p err..crit, range. Errors and criticals only.journalctl _PID=4521, by process. Use the PID literal, not--pid.journalctl _SYSTEMD_UNIT=nginx.service _UID=33, multiple field filters; AND'd together.
journalctl, time windows
The single biggest journalctl mistake is forgetting --since. Without it you're paging through last week. With it you're on the incident.
journalctl -u nginx --since "10 minutes ago", relative times work."yesterday","2 hours ago"all valid.journalctl -u nginx --since "2026-04-25 14:00" --until "2026-04-25 14:30", tight window. The incident-window default.journalctl -u nginx -f, follow. Live tail. Combine with-n 50to also show the last 50 first.journalctl -u nginx -e, jump to the end and stay. Pager mode, no follow.journalctl --boot, current boot only.--boot -1for previous boot.--list-bootsto see them.journalctl -u nginx --since today --output cat, just the message text, no timestamps. Easier to grep through.
Reload, restart, and the difference
Restart kills the process. Reload tells it to re-read config without dropping connections. Knowing which one your service supports avoids dropped traffic during a config push.
systemctl reload nginx, SIGHUP to nginx; rereads config; keeps connections.systemctl reload-or-restart nginx, reload if supported, else restart. The portable option.systemctl daemon-reload, reread unit files after editing them. Different from reloading the service itself. Forget this and your edits are ignored.systemctl cat nginx, the effective unit (main file + drop-ins concatenated). Always inspect before restarting.systemctl show nginx, every property as key=value.systemctl show nginx -p MainPIDfor one.systemctl reset-failed nginx, clear the failed state without restarting. Lets the next start attempt count fresh.
Override drop-ins
Never edit unit files directly. Distro upgrades will overwrite them. Drop-ins live alongside and survive everything.
systemctl edit nginx, opens an editor on a drop-in at/etc/systemd/system/nginx.service.d/override.conf. The right way.systemctl edit --full nginx, copies the unit file into/etc/systemd/system/for full editing. Use sparingly.- Drop-in template, section header is required, even if you're only setting one field:
[Service]
Environment="LOG_LEVEL=debug"
LimitNOFILE=65535 - To clear a value (not just override), assign the empty string first:
Environment=on its own line, then re-set. systemd-delta, lists every override on the system. Run it after a long absence to see what past-you did.- Always
systemctl daemon-reload && systemctl restart nginxafter editing a drop-in. The reload alone doesn't apply runtime values.
Timer units
cron's replacement, with logs that go to journalctl and dependency handling out of the box.
systemctl list-timers, all timers, next-fire times, last-fire times. The dashboard.systemctl list-timers --all, include disabled. Useful when something should have run.- Timer + service pair,
backup.timertriggersbackup.service. Same basename, different suffix. - Common timer keys:
OnCalendar=*-*-* 02:30:00(daily 02:30),OnBootSec=15min,Persistent=true(catch up missed runs). systemd-analyze calendar 'Mon..Fri 09:00', verify a calendar expression. Shows next 1 fire by default,--iterations=5for more.journalctl -u backup.service --since "1 week ago", what did the timer actually do all week. The audit trail cron never had.