Systemd

systemd the system daemon is a replacement for sysvinit. There is some controversy about it, since it is replacing many beloved system tools as loggers, cron, ntp.

Today, systemd is used in most of the Linux distributions as the start up method.

Linux for embedded systems often do not use systemd yet.

Using systemd makes the different Linux distributions very similar. What stays different is the package handling and management.

The most used command is systmctl

Note

The package manager installs in /usr/lib/systemd and customizations are done in /etc/systemd

If the same occurs in both location /etc/systemd has priority.

systemd also has introduced services run by the user and not as system service

/etc/mtab is handled differently since systemd does mounting. For backward compatibility do or check ln -sf /proc/self/mounts /etc/mtab

systemd does not require a udev package since it includes it (this has put the pressure to distributions using OpenRC to fork udev in a separate package).

systemd replaces ConsoleKit

Dealing with /etc/fstab additional .mount and .swap units can be automatically created

comment=systemd.automount

can be added to the drives in /etc/fstab to convert them to automount drives and not have the system waiting until such typically network drives are ready.

Since systemd is running all the time also a gui tool systemadm is available.

systemd-analyze tells how long the boot process was taking

There is support to make a svg graphics as bootchart systemd-analyze plot > plot.svg or systemd-analyze dot | dot -Tsvg > systemd.svg to convert it first to dot format and then having dot making the dependengy graph. Or simply see the ranking of what took long to start systemd-analyze blame

Keyboard layout can be listed as localectl list-keymaps and loaded as root with loadkeys <keymap as sg> or persistent by localectl set-keymap --no-convert <keymap> this modifies /etc/vconsole.conf obviously /etc/vconsole.conf could also be edited using an editor.

Modules not loaded automatically can be listed (one per line) and added to files like /etc/modules-load.d/<some name>.conf

The network must probably be started. In case of dhcp start the client daemon dhcpcd eth0 or start it via its unit systemctl start dhcpcd@eth0.service

Boot with systemd

The kernel must know to start systemd and not init after it has booted. For grub legacy put

kernel /vmlinuz root=/dev/sda2 init=/usr/lib/systemd/systemd

in /boot/grub/grub.conf and for grub 2 put

GRUB_CMDLINE_LINUX="init=/usr/lib/systemd/systemd"

in /etc/default/grub

Systemd units

The units are text files and have different file extensions as

  • *.service to start a service (e.g a daemon)

  • *.mount to mount a filesystem (there is also .automount)

  • *.socket prepare a socket for a listener and when accessed trigger an action

  • *.path to monitor accesses to a file or directory and trigger an action

  • *.timer to create a cron like timer that starts services

Unit files can be found on different locations:

  • /usr/lib/systemd/system/ installed by the package manager

  • /etc/systemd/system/ unites adapted for the system by the distribution and system administrator

  • /etc/systemd/user/ units for all users

  • ~/.config/systemd/user/ units for a dedicated user

systemctl --failed to show what failed

Available units can be seen by

ls /usr/lib/systemd/system

systemctl --all --full

systemctl list-units or simply systemctl

systemctl list-units --all

systemctl list-unit-files

systemctl | grep running

systemctl list-unit-files | grep enabled

systemctl is-enabled rpi-connect.service to see if it is enabled

sudo systemctl enable syncthing@<username>.service is a system service that requires a user being passed after the @ character

Customization can be made by copying and modifying those files to /etc/systemd/system

systemd calls more or less it units in parallel. If a unit calls an other that is not ready, then systemd buffers the request using sockets.

Systemd can create automatically additional units as when devices are plugged in. Therefore it uses in udev rules

TAG+="systemd"

Common section in systemd unit files

The unit files have different extensions but the file content has sections that are equal.

This section therefore descripes what is common and this will therefore not repeated in the dedication unit type sections.

Unit section
[Unit]
Description=<bla bla>
After=<*>.service

The unit section can hold:

  • After starts after the named service

  • Before starts before the named service

  • Wants starts the named service

  • Requires starts named service and when alive starts itself. It would terminate when the named service would die

Install section

The install section holds usually

[Install]WantedBy=multi-user.target

This line is used with systemctl enable <unit name>.<extension>

It creates a symlink in the multi-user.target.wants directory

When later the multi-user.target is started it looks into this directories

WantedBy lets the system continue n faillure RequiredBy would stop.

Systemd target units

systemd targets are used to group units and have them started together and form therefore something similar as runlevels in a sysvinit system.

*.target files can include other *.target files

/etc/systemd/system/default.target is a symlink to the default target

systemctl get-default shows this default targets that is run at boot

Common default targets are: multi-user.target, graphical.target, rescue.target

systemctl list-unit-files --type=target lists the unit files that are targets

systemctl set-default graphical.target sets the graphical desktop target

systemctl set-default multi-user.target sets the command line target

systemctl list-dependencies multi-user.target show what depends on it.

systemctl isolate multi-user.target will stop all targets except the multi-user.target

systemctl poweroff or poweroff turns off the computer

systemctl reboot or reboot reboots it.

More precise systemctrl calls the unit poweroff.target that is in /usr/lib/systemd/system

Systemd service units

To have a place where data can be persistent saved add:

[Service]
User=<user that runs the service if not root>
StateDirectory=<subdirectory created under /var/lib>
WorkingDirectory=/home/<username>
RuntimeDirectory=<subdirectory in /run>
RuntimeDirectoryMode=0755

For security reasons it is advised to run the service as a user

Adding a services to the list of being started at boot (the boot.target) is more uniform:

systemctl enable <name>.service enable automatic start at boot

systemctl enable --now <name>.service does two things enable automatic start at boot and starts it now

systemctl disable <name>.service disable automatic start at boot

systemctl is-enabled <name>.service shows if the service is enabled to automatic start at boot

systemd handle services as known from sysvinit systems:

systemctl start <name>.service starts a service

systemctl stop <name>.service stops a service

systemctl restart <name>.service stops and then starts a service

systemctl reload <name>.service similar to restart is reload however normal functionality of the service keeps maintained.

systemctl status <name>.service shows the status

systemctl mask <name>.service the service can no be started even if the the system tries it

systemctl --user status <name>.service shows the status of a user service

systemctl cat <name>.service to read the file without dealing with its path

systemctl list-dependencies <name>.service or systemctl list-dependencies --all <name>.service to see its dependencies

systemctl show <name>.service to see the low level details

Type= defines when the service is considered to be successful. Values are:

  • exec it must running

  • simple as exec but not detail time consuming checking if it is well running. It is the default and therefore does not have to be declared.

  • oneshot it is normal that it runs and then terminates

The command follows ExecStart=

It is possible to add ExecStartPre and ExecStartPost= to add additional commands

Restart=OnFailure allows to restart the command. There are also option to configure the restart behavior

There are many options to make it more secure:

User=_

DynamicUser=yes

NoNewPrivileges=yes

ProtectHome=

ProtectSystem=

PrivateDevices=

ReadOnlyPaths=

PrivateNetworks

override systemd services

Instead of modifying a service file installed by the system to /usr/lib/systemd/system/<name>.service and risk to have it overwritten with the next update or risk a disaster, an override can be applied with systemctl edit <name>.service

The original file /usr/lib/systemd/system/<name>.service stays untouched

The result will end up in /etc/systemd/system/<name>.service.d/override.conf

additional *.conf files can be added and are executed in alphabetical order

systemctl cat <name>.service to see the result of the override

Important

systemctl daemon-reload and systemctl restart <name> to have it applied.

To revert delete the /etc/systemd/system/<name>.service.d/override.conf or systemctl revert <name> and run systemctl daemon-reload and systemctl restart <name>

Linger

sudo loginctl enable-linger <username> to start the <username> services at startup

loginctl show-user $USER | grep Linger to see if it is enabled

sudo loginctl disable-linger $USER to disable it

Systemd timer units and timesyncd

sytemd-timesyncd is a time framework that handles the system clock and can also replace cron.

Systemd Time

timedatectl should be run to see it NTP is enabled, if not timedatectl set-ntp true will enable it.

timedatectl timesync-status will show if it is happy

To have it permanently active check and edit /etc/systemd/timesyncd.conf

NTP=0.pool.ntp.org 1.pool.ntp.org 2.pool.ntp.org FallbackNTP=ntp.ubuntu.com

An other NTP services as chronyd are not required and might cause conflicts.

systemd cron alternative

For backward compatibility reasons crontab is usually still working on systemd systems. The systemd way is however using timer unit files.

Those are *.timer files

[Unit]
Description=example timer
[Timer]
OnCalendar=Mon 09:00:00
[Install]
WantedBy=timers.target

Important

The *.timer file starts a *.service file having the same name. The service file should contain

[Service]Type=oneshot

So systemd knows it will be normal to run and then terminate. On other services this behavior might be considered as a crash and cause a restart.

timers.target starts all *.timer files after boot

The [Timer] section allows different settings as:

  • OnCalendar= to set a calendar date supporting with * wildcards and with commas lists as Mon,Wed,Fri or ranges as Mon..Fri. https://systemd.guru/ lets play with. systemd-analyze calendar "Mon 09:00:00" will also show what it would do with the calendar string

  • OnBootSec= starts x seconds after boot

  • OnUnitActiveSec= starts x seconds after the service unit starts

  • OnUnitInactiveSec= starts x second after the unit has terminated, so no reentered service unit will happen

  • Persistent=true will check if unit calls have been missed during the time the system was not powered and if so, start the service unit

  • Unit= has to be use it the *.timer has an other name as the *.service file to be called.

systemctl <start,stop, status, enable> *.timer is used to operate the timer.

systemctl list-timers will show the active timers

Systemd directories wants and requires

Directories as <xxx>.<target, service>.wants or <xxx>.<target, service>.requires exist. This is a second and dynamic way to add dependencies to units.

A user-created.service might have

[Install]
WantedBy=multi-user.target

if enabled systemctl enable user-created.service then

ls -la /etc/systemd/system/multi-user.target.wants/

will show a symlink to /etc/systemd/system/user-created.service

Journal the systemd logger

systemd does not need a logger since it includes the logger journal. It can be configured via /etc/systemd/journald.conf

To have the log stored on the disk /var/log/journal

Storage=persistent

or mkdir -p /var/log/journal

To set maximum size on disk

SystemMaxUse=50M

Limits to 50MByte if this is missing it will be limited to 10% of the partition size.

The log is binary and not ASCII and can be read via journalctl

For just the current boot journalctl -b

For the kernel messages journalctl -k.

journalctl -eu <name>.service will show what has been logged for a service and with e jump to the end of the log.

The journal can feed a classic logger by systemctl enable syslog-ng so the log becomes ASCII again.

journalctl -b --no-pager | grep <word to be in the line>


Linurs startpage