Systemd service syntax

From wikinotes

Documentation

All config opts https://www.freedesktop.org/software/systemd/man/systemd.directives.html
man systemd.unit https://man.archlinux.org/man/core/systemd/systemd.unit.5.en
man systemd.service https://man.archlinux.org/man/core/systemd/systemd.service.5.en
man systemd.target https://man.archlinux.org/man/systemd.target.5

Locations

/etc/systemd/{user,system}/*.service systemwide user/system unitfiles
/usr/lib/systemd/{user,system}/*.service package user/system unitfiles
~/.config/systemd/user/*.service user unitfiles

Tutorials

archwiki: user services https://wiki.archlinux.org/title/Systemd/User

Example

[Unit]
Description=Daemon to detect crashing apps
Requires=display-manager.service network-online.target
After=ctrl-alt-del.target

[Service]
ExecStart=/usr/sbin/abrtd
Type=forking


[Install]
WantedBy=multi-user.target

Sections

[Unit]:

A service file will launch system services, devices, mount points and more. The word that encompasses all of these terms is unit. This section is where you write a description for the service, and also set the dependencies. There are two options for Dependencies:

  • After= Script will not be launched until after this service is started
  • Requires= Script will not be launched unless required service has been started.

You may have multiple dependencies for After and/or Requires, simply separate each service by a space. Here is a complete list of services that are triggered for special events like when the internet is connected, CTRL-ALT-DELETE is executed, or the start of a display manager. http://0pointer.de/public/systemd-man/systemd.special.html

You can find the order of execution of systemd services (units) with:

systemd --test --system | grep Unit | grep -
[Unit]
Description=Daemon to detect crashing apps
Requires=display-manager.service network-online.target
After=ctrl-alt-del.target

[Service]

The service section is for information related to starting services only. Mount points, Devices, Timers etc do not need this section. There are two arguments here:

  • ExecStart= links to the binary you want to run
  • Type= defines the type of service that you would like

Your options for type are as follows:

simple let systemd manage the process, no fork() call required. (bash scripts, python scripts, ...)
forking Traditional Init way. Process is forked to the background but listed as the main daemon process. you are apparently responsible for calling fork() yourself.
oneshot Run Once, and Terminate before running next unit.
dbus ???
notify Same as simple, except expects output to sd_notify when it has finished running. (notifies systemd when finished running)
idle Waits for currently running jobs are dispatched to run (to not push info from multiple jobs to console)
[Service]
ExecStart=/usr/bin/python /some/script.py
Environment='PYTHONPATH=/home/will/progs/python/general/projects:/home/will/progs/python/general:/home/will/progs/maya/m2014/pythonScriptLib'
Environment='PIPELINE_PYTHONSTART=/home/will/.pythonrc'
Type=simple

[Install]

This install section determines what your service should wait for in order to run.

[Install]
WantedBy=graphical.target

Some common targets:

graphical.target          # after x11 starts
bluetooth.target          # after bluetooth starts
network-online.target     # wait until a routable ip address is up
multi-user.target         # immediately once graduating from single-user mode.


List all targets:

ls -l /usr/lib/systemd/system/*.target
Sources:
https://www.freedesktop.org/wiki/Software/systemd/NetworkTarget/
http://0pointer.de/blog/projects/systemd-for-admins-3.html
http://www.linux.com/learn/tutorials/527639-managing-services-on-linux-with-systemd

Configurable Services

Run As User

You can do this in 2x ways:

systemctl --user

You can do this with any service.

systemctl --user enable mpd.service

mpd@user.service

You configure the user/group a systemd service runs as with the User and Group keys under the [Service] Category.

These can be made configurable with the %I value. In order to indicate this to your user, your service must be in the format myservice@.service.

[Service]
User=%I
Group=%I
# You can then start your service by starting/enabling it with
systemctl enable myservice@will.service

Configurable Variables

You can write configurable services using bash-like variables.
Then name combination of variable-values in /etc/default

# /etc/systemd/system/yourservice@.service
[Service]
ExecStart=${COMMAND} ${ARGS}
# /etc/default/yourservice@echo-hi
COMMAND=echo
ARGS=hi

# /etc/default/yourservice@echo-hello
COMMAND=echo
ARGS=hello
systemctl enable yourservice@echo-hello.service

Service Overrides

You can also override any service independent of the OS packages even if they are not designed to be customizable.

# creates /etc/systemd/system/myservice.service.d/override.conf
systemctl edit myservice.service

Features

Auto Restarts

The following options together as used to configure service restart behaviour.
Note that StartLimitIntervalSec must be greater than RestartSec * StartLimitBurst.

[Unit]
# retry a max of 5 times within `StartLimitIntervalSec`
StartLimitBurst=5

# Units started more than `StartLimitBurst` times
# within `StartLimitIntervalSec` are not permitted to restart anymore
StartLimitIntervalSec=200

[Service]
# restart on non-zero exit-code
Restart=on-failure

# Time to sleep before restarting a service
RestartSec=