ruk·si

systemd

Updated at 2017-07-09 23:51

systemd is system management software (init system); it keeps other userspace processes running. It was created in 2010 to unify init system configuration on various Linux distributions.

Your Linux will most likely be running at least two instances of systemd as you login.

  1. System-wide systemd instance, always running as PID 1.
  2. User-specific systemd instances that are stopped when user logs out.

systemd manages units. Unit refers to any resource that systemd knows about and can manage; like a service, device, mount, timers, etc. These are defined in unit files.

systemd will read unit files from various locations:

  • System services are read from /etc/systemd/system/*
  • User services are read from /etc/systemd/user/*

Get familiar with systemd by checking what it's currently running:

systemctl list-units
systemctl list-units --failed  # check if some of your systemd units are failing

Example

Let's create a service that prints runtime information and greets every 10 seconds.

sudo su

# create a user+group without password or home directory
useradd --system --comment "Greeter; a systemd example, delete me" greeter

# create directory to install our software, note this sets ownership only to last dir
install -d -m 0700 -o greeter -g greeter /opt/greeter

# create an example program that we'll wrap as a service
install -o greeter -g greeter -m 0700 /dev/stdin /opt/greeter/start.sh <<'EOF'
#!/bin/bash
set -xeuo pipefail
id
pwd
printenv
while $(sleep 10);
do
    echo "Hello!"
done
EOF
install -o greeter -g greeter -m 0700 /dev/stdin /opt/greeter/stop.sh <<'EOF'
#!/bin/bash
set -xeuo pipefail
echo "Bye Bye!"
EOF

# Create a separate configuration file to specify environmental variables.
# We don't use "Environment=" definitions as those are shown in `systemctl show`
# There has been talks that environmental variables are inherently insecure
# but this is commonly good enough; a file that is only readably by the service
# account and administrators.
install -d -m 0700 -o greeter -g greeter /etc/greeter
install -D -o greeter -g greeter -m 0600 /dev/stdin /etc/greeter/environment.conf <<'EOF'
SECRET="123456789"
EOF

# try it out, CTRL+c to exit when done
bash /opt/greeter/start.sh

Then create a small systemd description how to run the service:

install -m 0600 /dev/stdin /etc/systemd/system/greeter.service <<'EOF'
# "Description" is, contrary to what you might expect, a short, human readable name
#               and not a long description what the unit file does, otherwise
#               the unit will be referred by the filename e.g. `greeter.service`
# "Wants" is a weak requirement; tires to start/wait the target but won't fail it it does
# "After" is an ordering definition; "start this after networking is up an running",
#         and "stop this service before stopping network stack".
# "network.target" means that the network software stack is up and running,
#                  but it does not mean that we have any working connection
#                  apart from localhost.
[Unit]
Description=Greeter Service
Wants=network.target
After=network.target

# By default, the service would run under "root" user and we don't want that.
[Service]
User=greeter
Group=greeter
WorkingDirectory=/opt/greeter
EnvironmentFile=/etc/greeter/environment.conf
ExecStart=/opt/greeter/start.sh
ExecStop=/opt/greeter/stop.sh
Restart=always

# start this service when multi-user shell is activated (runlevel 2)
[Install]
WantedBy=multi-user.target
EOF

You control services with systemctl.

# as we modified available services, force systemd to reindex it's inventory
# this should be ran each time you modify systemd units
systemctl daemon-reload

# enable starting on reboot
systemctl enable greeter

# start service right way
systemctl start greeter

# see service status and some of the latest logs
systemctl status greeter

# follow the logs as they come in
journalctl -u greeter -f

# restaring will first call the ExecStop and then ExecStart again
systemctl restart greeter

# open all logs, showing latest entries first
journalctl -u greeter -r

# you can try killing the process and see if it spins up properly
ps -f -u greeter
kill 2274876
# you will notice a new one is created by calling ExecStop and ExecStart again

Cleanup:

systemctl stop greeter
systemctl disable greeter
rm /etc/systemd/system/greeter.service
systemctl daemon-reload
rm -rf /opt/greeter /etc/greeter
userdel greeter

Sources