tmpfiles.d is a service for managing temporary files and runtime directories for daemons. In this guideline we mainly concentrate on how it is used to populate /run
and /run/lock
. Since /run
is a tmpfs
filesystem, it and its contents must be recreated on every reboot. For files intended to be created there, this should normally not pose any problems. However, directories will often need to be created ahead of time. This is best done using the tmpfiles.d mechanism.
Asking the tmpfiles.d mechanism to create directories for you just involves dropping a file into %{_tmpfilesdir}
.
For example, if the package needs a few directories to be created in /run
in order for it to run, the packager needs to create a file named %{name}.conf
that is installed as %{_tmpfilesdir}/%{name}.conf
. The file has one or more lines of the following format:
d /run/NAME PERM USER GROUP -
The format of the line is as follows:
d
specifies that a directory is to be created if it doesn't exist. You can use a different type specifier if you need it. See man
tmpfiles.d
for possible values./run/NAME
is the filesystem path to create.PERM
are the permissions (in the 4-digit octal format) to apply to the directory when it is created.USER
is the name of the owner of the directory.GROUP
is the name of the group of the directory.-
specifies that aging should not be applied to the contents of the directory. Aging is a mechanism for automated cleanup of files that were not used for a specified length of time. This is mostly useful for directories such as /tmp and is seldom used by packages. Feel free to use aging if it is appropriate for your directory.An example:
d /run/mysqld 0755 mysql mysql -
Information on other options is available on the tmpfiles.d man page should you need to do something more advanced.
In the spec file, the packager needs to install the tmpfiles.d conf file into the %{_tmpfilesdir}
directory and also make sure the directory is included in the rpm.
# tmpfiles.d configuration for the /run directory
Source1: %{name}-tmpfiles.conf
[...]
%install
mkdir -p %{buildroot}%{_tmpfilesdir}
install -m 0644 %{SOURCE1} %{buildroot}%{_tmpfilesdir}/%{name}.conf
# The next two lines may not be needed if the upstream's install script creates them
mkdir -p %{buildroot}/run
install -d -m 0755 %{buildroot}/run/%{name}/
# A bit contrived as most packages will either create a subdirectory or a single file. Not both
install -m 0644 %{buildroot}/run/%{name}.pid
[...]
%files
%dir /run/%{name}/
%verify(not size mtime md5) /run/%{name}.pid
%{_tmpfilesdir}/%{name}.conf
%{_tmpfilesdir}
expands to %{_prefix}/lib/tmpfiles.d
which is the location that the package's default tmpfile creation scripts should install into. %{_tmpfilesdir}/%{name}.conf
is not marked as a %config
file because it is not supposed to be edited by administrators. Administrators can override the package's %{name}.conf
by placing an identically named file in /etc/tmpfiles.d/
, but this should very rarely be needed.
Files (not directories) that the program places directly into /run
are listed in the %files
section as %verify(not
size
mtime
md5)
so that rpm knows the file must exist as part of this package but will not complain when the file contents change. Files placed in the subdirectories may be listed the same way or omitted entirely as the files will be cleaned up on every reboot.
There are multiple ways to try creating the directories but most suffer some disadvantage that tmpfiles.d addresses:
Many times, daemons run as an unprivileged user who would not be allowed to create new directories directly into /run
.
If the daemon does not drop privileges, then you can patch it to create the files and directories when the daemon starts and submit the patch upstream.
Since the init script is run by root, before the daemon drops privileges, why not create the directories there?