systemd

systemd is a software suite for the Linux operating system. Its primary component is an init system used to bootstrap user space and manage user processes. It also provides replacements for various daemons and utilities, including device management.

SysVinit

In the older days SysVinit was used to start and stop services. You would find in /etc/init.d/ a script for each service that understand parameters like start stop restart

In folders like /etc/rc3.d/ you would find links to those scripts.

This shows the current runlevel

who -r

This switches to another one

init 3

Really easy to understand and powerful, but you have to write lots of shell scripts and and starting things in parallel is hard.

Terms

https://www.golinuxcloud.com/beginners-guide-systemd-tutorial-linux/

targetis a group of services, similar to, but more general than, a System V runlevel. There is a default target which is the group of services that are started at boot time.
serviceis a daemon that can be started and stopped, very much like a SystemV service
unitis a configuration file that describes a target, a service, and several other things. Units are text files that contain properties and values.

Configuration

  1. /etc/systemd/system: Local configuration
  2. /run/systemd/system: Runtime configuration
  3. /lib/systemd/system: Distribution-wide configuration
  4. /usr/lib/systemd/system/: Package configurations from deb / rpm

systemd checks them in order

Run your own service in systemd

Put this in

/etc/systemd/system/foo.service
[Unit]
Description=My nice service
After=syslog.target
Requires=local-fs.target
Requires=network-online.target

[Service]
ExecStart=/usr/sbin/foo --bar
Type=simple
Restart=on-failure

[Install]
WantedBy=multi-user.target

After every change you made you need to this

systemctl daemon-reload

After and Before just help to get the order right, Requires defines the order and also that a service is not started if the required one failed already.

To get all the valid targets do

systemctl list-units --type=target

If the service should be started automatically you need to run

systemctl enable foo.service

If your services forks something in the background you need to write its pid into a file so we can kill it

[Unit]
Description=My forker
Requires=local-fs.target

[Service]
User=mrfoo
RuntimeDirectory=/var/run/foo/
ExecStart=/usr/bin/mrfoo --bar
Type=forking
PIDFile=/var/run/foo/mrfoo.pid

[Install]
WantedBy=multi-user.target

Service that creates a folder if not yet there

[Unit]
Description=Create folder
Requires=local-fs.target

[Service]
ExecStartPre=-/bin/mkdir /var/run/hadoop
ExecStart=/bin/chown thorsten /var/run/hadoop
Type=oneshot

[Install]
WantedBy=multi-user.target

Types of services

simple (default)If you would start it via the command line the prompt would only return once the program finishes
forkingIf you would start it via the command line the prompt would return but the program would keep on running in the background.
oneshotIf you would start it via the command line it would do something, then finish and return the prompt to you. You may want to set RemainAfterExit=yes as well so that systemd still considers the service as active after the process has exited.
idlesystemd will delay execution of the service binary until all jobs are dispatched. Other than that behavior is very similar to Type=simple.

Restart policy

By default if your service stops it is NOT restarted, no matter if it stopped with an error or normally

[Unit]
Description=Restart demo

[Service]
ExecStart=/bin/ls /doesNotExist

You can tell systemd to restart in case it failed

[Unit]
Description=Restart demo

[Service]
Restart=on-failure
ExecStart=/bin/ls /doesNotExist

But if your service restarts too often this is stopped as well

Scheduled restart job, restart counter is at 5.
systemd[1]: Stopped Restart demo.
systemd[1]: Start request repeated too quickly.

If you want to restart forever, you need to ensure that within the StartLimitIntervalSec the number of restarts always stays below StartLimitBurst. RestartSec adds pauses to achieve this

[Unit]
Description=Restart demo

# If number of restarts in this time was higher than this give up permanantly
# By doing a 5 second break after each fail, in 60 seconds there can only by 12 fails, so 15 can not be reached
StartLimitIntervalSec=60
StartLimitBurst=15

[Service]
Restart=always
# minimum time between 2 restarts
RestartSec=5
ExecStart=/bin/ls /doesNotExist

Cheat sheet

systemctl daemon-reload
systemctl start foo
systemctl enable foo
systemctl stop foo

Turn a service off You can stop a service. Might be started again later

systemctl stop ntpd.service
# service ntpd stop

Kill a service (try to stop if first)

systemctl kill -s SIGKILL foo.service

You can disable a service. It will no longer be activated on boot, or any other activation. You can still start it manually if you wish.

systemctl disable ntpd.service

Stop it from being started at all

ln -s /dev/null /etc/systemd/system/ntpd.service
systemctl daemon-reload

List all services and what their status is

systemctl
systemctl status
ps xawf -eo pid,user,cgroup,args
cgroup tree

Who needs a unit?

systemctl show -p "Wants" multi-user.target

Why does starting take so long?

systemd-analyze blame
systemd-analyze plot > plot.svg

Current runlevel

systemctl list-units --type=target

Switch runlevel

systemctl isolate runlevel5.target
systemctl isolate graphical.target