systemd
Managing services
$ systemctl status sshd # state, recent logs, main PID
$ systemctl start sshd # also stop / restart
$ systemctl reload sshd # re-read config without a full restart
$ systemctl enable --now sshd # start now AND on every boot
$ systemctl disable --now sshd
$ systemctl is-active sshd; systemctl is-enabled sshd
$ systemctl mask sshd # fully block it (symlink to /dev/null)
Listing and inspecting units
$ systemctl list-units --type=service # running units
$ systemctl list-units --state=failed # what is broken
$ systemctl list-unit-files --state=enabled # enabled on boot
$ systemctl cat sshd # show the unit file(s)
$ systemctl show sshd -p MainPID,ActiveState # raw properties
$ systemctl daemon-reload # after editing a unit by hand
Overriding a unit (drop-ins)
Don’t edit vendor units in /usr/lib; use a drop-in so changes survive
package updates:
$ systemctl edit sshd # creates /etc/systemd/system/sshd.service.d/override.conf
[Service]
Restart=always
Environment=FOO=bar
Writing a unit
/etc/systemd/system/myapp.service:
[Unit]
Description=My app
After=network-online.target
Wants=network-online.target
[Service]
ExecStart=/usr/local/bin/myapp
Restart=on-failure
User=myapp
[Install]
WantedBy=multi-user.target
journalctl
$ journalctl -u sshd # logs for one unit
$ journalctl -u sshd -f # follow, like tail -f
$ journalctl -b # this boot; -b -1 = previous boot
$ journalctl -p err # priority err and worse
$ journalctl --since "10 min ago" --until now
$ journalctl -k # kernel messages (dmesg)
$ journalctl --disk-usage; journalctl --vacuum-time=7d
Timers (a cron replacement)
A .timer triggers the .service of the same name. backup.timer:
[Unit]
Description=Nightly backup
[Timer]
OnCalendar=*-*-* 02:00:00 # daily at 02:00
Persistent=true # run on next boot if a scheduled run was missed
[Install]
WantedBy=timers.target
$ systemctl enable --now backup.timer
$ systemctl list-timers # next/last run of every timer
Targets (runlevels)
$ systemctl get-default
$ systemctl set-default multi-user.target # boot without a GUI
$ systemctl isolate multi-user.target # switch now, no reboot
Boot analysis
$ systemd-analyze # total boot time
$ systemd-analyze blame # slowest units
$ systemd-analyze critical-chain # the critical boot path
User units
Run units as your own user (no root) - this is how rootless container quadlets run:
$ systemctl --user enable --now myapp.service
$ loginctl enable-linger $USER # let user units run without an active login