Day 28 in the #vDM30in30
Image source: https://flic.kr/p/y1DUPj
So previously I blogged about about how to ensure a
/var/run directory exists before a systemd service starts, using the
ExecStartPre steps to ensure the directory exists.
ExecStartPre=-/usr/bin/mkdir /run/jmxtrans/ ExecStartPre=/usr/bin/chown -R jmxtrans:jmxtrans /run/jmxtrans/
I took the idea from a blog by Jari Turkia.
However, I made the rookie mistake of not checking the comments to see if things had changed and there was a better way, since the original post was written in 2013.
In March 2014, there was a new new
RuntimeDirectory setting. It was made exactly for this use-case:
System daemons frequently require private runtime directories below /run to place communication sockets and similar in. For these, consider declaring them in their unit files using RuntimeDirectory= (see systemd.exec(5) for details), if this is feasible.
This has been available since systemd 211.
So the systemd service file will actually be much easier:
[Unit] Description=JMX Transformer - more than meets the eye After=syslog.target network.target [Service] Type=forking User=jmxtrans Group=jmxtrans RuntimeDirectory=jmxtrans PIDFile=/var/run/jmxtrans/jmxtrans.pid ExecStart=/usr/share/jmxtrans/bin/jmxtrans start [Install] WantedBy=multi-user.target
As we only have to specify the
Funnily enough this also happened in the Redis module I was working on.
I found that the Beaker tests would sometimes fail with Debian 8 (Jessie), which was using a redis package.
It was using the
dotdeb-redis package which had a systemd file that looked like this:
[Unit] Description=Advanced key-value store After=network.target Documentation=http://redis.io/documentation, man:redis-server(1) [Service] Type=forking ExecStart=/usr/bin/redis-server /etc/redis/redis.conf PIDFile=/var/run/redis/redis-server.pid TimeoutStopSec=0 Restart=always User=redis Group=redis ExecStartPre=-/bin/run-parts --verbose /etc/redis/redis-server.pre-up.d ExecStartPost=-/bin/run-parts --verbose /etc/redis/redis-server.post-up.d ExecStop=-/bin/run-parts --verbose /etc/redis/redis-server.pre-down.d ExecStop=/bin/kill -s TERM $MAINPID ExecStopPost=-/bin/run-parts --verbose /etc/redis/redis-server.post-down.d PrivateTmp=yes LimitNOFILE=65535 PrivateDevices=yes ProtectHome=yes ReadOnlyDirectories=/ ReadWriteDirectories=-/var/lib/redis ReadWriteDirectories=-/var/log/redis ReadWriteDirectories=-/var/run/redis CapabilityBoundingSet=~CAP_SYS_PTRACE # redis-server writes its own config file when in cluster mode so we allow # writing there (NB. ProtectSystem=true over ProtectSystem=full) ProtectSystem=true ReadWriteDirectories=-/etc/redis [Install] WantedBy=multi-user.target Alias=redis.service
So this service file would have the same issue: if the directory for the pid was missing, it would refuse to start:
root@debian-redis-test:~# systemctl stop redis-server root@debian-redis-test:~# rm -rf /var/run/redis/ root@debian-redis-test:~# systemctl start redis-server Job for redis-server.service failed. See 'systemctl status redis-server.service' and 'journalctl -xn' for details. root@debian-redis-test:~# journalctl -u redis-server --no-pager | grep pid Nov 30 13:29:04 debian-redis-test systemd: PID file /var/run/redis/redis-server.pid not readable (yet?) after start-post.
I would assume this would affect the upstream debian package, but for some reason it's not... but I thought it would be a good idea to add that field to the systemd unit file anyways. Plus it gives me an excuse to open my first Debian bug: