Systemd manages different types of units. The service unit being the most common one, representing a service or daemon. A unit file contains the configuration regarding a single unit. In case of a service unit, how to start and stop the service, how to check if the service and its dependencies are running.
In this Article, we show and explain some examples which can help as a starting point to write your own systemd units. For more complex requirements, we show some examples which you may like to extend your unit with.
The unit files for the user instance are usually stored in
~/.config/systemd/user. The name of the file defines the name and type of the unit. The file
~/.config/systemd/user/myredis.service defines a service unit named myredis.
The Unit files are commonly split into three parts. The Unit section contains some meta-data about the unit. The second section is named after the unit type, where Service is the most common. In this section, you can define what the unit does and how. The Install Section contains information about how to activate/deactivate a unit.
Information about how to manage units can be found in the following article: Manage daemons as user with systemd
This example starts a Redis server on port 7777. The Unit section only defines the description and an (optional) url as documentation. The Service section defines the start and stop commands. The stop command is optional. If systemd stops a service, it will first execute the stop command and then kill all leftover processes of this unit.
# ~/.config/systemd/user/myredis.service [Unit] Description=Custom Redis on Port 7777 Documentation=https://support.nine.ch/a/2xNbpLp-SpQ [Service] ExecStart=/usr/bin/redis-server --port 7777 ExecStop=/usr/bin/redis-cli -p 7777 shutdown [Install] WantedBy=default.target
Systemd prefers services which do not daemonize themselves. If your application does daemonize, you need to tell systemd about it. This is done by setting the Service Type to forking. Further, it is recommended to define the
PIDFile option to tell systemd which process is the main process.
%h is replaced with the user home directory and
%pwith the name of the unit. Specifiers like this can help creating more robust and portable unit files. More specifiers can be found in the systemd.unit man-page.
# ~/.config/systemd/user/myredis.service [Unit] Description=Custom Redis on Port 7777 Documentation=https://support.nine.ch/a/2xNbpLp-SpQ [Service] Type=forking ExecStart=/usr/bin/redis-server --port 7777 --daemonize yes --pidfile %h/.%p.pid ExecStop=/usr/bin/redis-cli -p 7777 shutdown PIDFile=%h/.%p.pid [Install] WantedBy=default.target
Templates are a powerful tool of systemd. Units with names ending in
@ are considered a template. This enables you to launch multiple similar instances of the same service. If you paste the following example into a file named myredis@.service, you can launch multiple instances of it like myredis@7777 and myredis@7778. The part behind the
@ is then factored in to the
# ~/.config/systemd/user/myredis@.service [Unit] Description=Custom Redis on Port %i Documentation=https://support.nine.ch/a/2xNbpLp-SpQ [Service] ExecStart=/usr/bin/redis-server --port %i ExecStop=/usr/bin/redis-cli -p %i shutdown [Install] WantedBy=default.target
Advanced Configurations Snippets
If you need some extra steps to setup or teardown your service, you can use the Pre/Post Start/Stop actions. You can add the same parameter multiple times if you need to. By prefixing your command with a
-, you can tell systemd to ignore errors of this command. Otherwise, the service is not started if the Pre-Start command fails.
[Service] ExecStartPre=/bin/mkdir -p /tmp/mytempdir ExecStartPre=-/bin/false ExecStartPost=/usr/bin/touch /tmp/mytempdir/started ExecStopPost=/bin/rm -rf /tmp/mytempdir
If your service is capable of reloading its configuration, you can use the
ExecReload parameter to specify how to trigger the reload. The
$MAINPID variable is set to the main process of the daemon.
[Service] ExecReload=/bin/kill -HUP $MAINPID
With the Restart parameter, you can specify whether systemd should restart the unit if it exits unexpectedly. The default is
always could save you some trouble:
Setup the Environment
Sometimes, it is required to setup the environment for a service. With systemd, you can setup the working directory and additional environment variables quite easily.
The files specified with
EnvironmentFile does override variables set with
Environment. The file needs to exist unless it is prefixed with a
-. The syntax for the
EnvironmentFile is a shell-like
[Service] WorkingDirectory=/home/www-data/servicedir Environment=ENV=production EnvironmentFile=-/home/www-data/servicedir/.env