4

Having written several small daemons or web applications for my personal use, I like to manage them using systemd (I am using Arch Linux, if that matters). So I write service files like the one below:

[Unit]
Description=My example daemon

[Service]
Type=forking
User=example_user
ExecStart=/path/to/my_executable
ExecStop=kill -QUIT $MAINPID
PIDFile=/var/run/example/example.pid

[Install]
WantedBy=multi-user.target

my_executable fails to start if it cannot write its PID file, which generally means that the directory /var/run/example/ does not exist. This happens after every reboot since I have /var/run of a tempfs.

One solution is to start my_executable as root and have it drop to the correct access rights after creating its environment, but I not really comfortable with that, since I don't trust myself to do it correctly.

Is there a way to make systemd do the heavy lifting here (maybe by specifying another script that should run before doing ExecStart)? What is the best way?

6

systemd provides systemd-tmpfiles for this exact purpose. The systemd-tmpfiles service handles the creation, cleaning and removal of volatile and temporary files and directories which usually reside in directories such as /run or /tmp. The configuration of systemd-tmpfiles is described in the manual page of tmpfiles.d1.

Create a systemd-tmpfiles configuration file for your service in one of the configuration paths, e.g. etc/tmpfiles.d. The format of the configuration file is one line per path, of the form:

type path mode ownership age argument

For instance, the line

d /var/run/example 0755 example_user - -

tells systemd-tmpfiles to create the directory /var/run/example owned by example_user if doesn't already exist.

1 The Arch Linux wiki article on systemd also provides some examples regarding systemd-tmpfiles configuration.

0

For your exact situation, the service file would look something like this:

[Unit]
Description=My example daemon

[Service]
Type=forking
User=example_user
# Run ExecStartPre with root permissions
PermissionsStartOnly=true
ExecStartPre=-/bin/mkdir /var/run/example
ExecStartPre=/bin/chown -R example_user /var/run/example/
# Run ExecStart with example_user permissions
ExecStart=/path/to/my_executable
ExecStop=kill -QUIT $MAINPID
PIDFile=/var/run/example/example.pid

[Install]
WantedBy=multi-user.target

(source)

Note: you might want to check the paths to chown and to mkdir first.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.