Tech Chorus

Systemd Unit File Just To Create A Directory Under /run

written by Sudheer Satyanarayana on 2018-01-19

On recent versions of Fedora, CentOS and RHEL, /var/run and /var/lock are mounted as /tmpfs. Also, /var/run is a symlink to /run. Because of this, if you create a directory under /run it won't stay there after a reboot.

If you are starting to migrate your service to systemd or just want to create a directory under /run using systemd, use this simple unit file. The contents of:

/etc/systemd/system/my.service
[Unit]
Description=My Service

[Service]
# We just want to create the myservice run directory
Type=oneshot
RuntimeDirectory=myservice
User=myuser
Group=myuser
ExecStart=/bin/true
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target

Replace my.service with an appropriate name for your service. Replace the description, User and Group values to your needs.

Start the unit:

systemctl start my.service

Enable the unit so that it starts when the system boots:

systemctl enable my.service

What is wrong in using ExecStartPre=-/bin/mkdir /var/run/myservice?

Systemd can handle directory creation and setting up its attributes for you. You just specifiy the name of the directory in the RuntimeDirectory= directory. When the unit starts, systemd creates the directory and sets its owner and group to the values you specify in User= and Group= directives. So, the counter question is, when systemd can do it for you using a simple directive, why do you want to do it yourself? Also, note that the - prefix just ignores the error when the directory already exists and another attempt is made to create it. Although the error is ignored, it still shows up in red when you check the status of the service.

What is Type=oneshot?

Type=oneshot means the process is expected to exit before systemd starts follow-up units. Along with this, we also specify RemainAfterExit=yes. We tell systemd that my.service shall be considered active even when all its processes exited. When you query the status of the service, you will see that the unit is active because of this directive.

What is ExecStart=/bin/true?

Typically, you would put the path to your service executable in ExecStart= directive. In our example, we're not doing that yet. We're simply using the sytemd unit file to create the /run/myservice directory. So, we use the placeholder command /bin/true. /bin/true simply returns 0 indicating that the command was executed successfully.

References