RHEL

Have you ever used a temporary directory? I'm guessing if you use a computer, you've used one of these. It's a core feature of nearly every operating system. To ensure system stability, you should always check that filesystems on which a temporary directory resides don't get full—running out of space can quickly bring your system to a grinding halt.

One method to prevent running out of space could be to place those directories on a dedicated partition, but no matter the solution, it is a best practice to clean those directories periodically, based on you/your app's needs.

Red Hat Enterprise Linux (and Fedora as well) provides a more structured and configurable method to manage temporary directories and files: systemd-tmpfiles.

How systemd-tmpfiles work

Once a Red Hat-like system boots up, a special unit file is executed: systemd-tmpfiles-setup, this unit will execute the systemd-tmpfile --create --remove command.

You can take a look at the systemd unit file by executing the following commands:

[root@freddy ~]# systemctl status systemd-tmpfiles-setup.service
● systemd-tmpfiles-setup.service - Create Volatile Files and Directories
   Loaded: loaded (/usr/lib/systemd/system/systemd-tmpfiles-setup.service; static; vendor preset: disabled)
   Active: active (exited) since Thu 2016-08-18 20:06:04 CEST; 2 weeks 2 days ago
     Docs: man:tmpfiles.d(5)
           man:systemd-tmpfiles(8)
 Main PID: 1007 (code=exited, status=0/SUCCESS)
    Tasks: 0 (limit: 512)
   CGroup: /system.slice/systemd-tmpfiles-setup.service

Aug 18 20:06:04 freddy systemd[1]: Starting Create Volatile Files and Directories...
Aug 18 20:06:04 freddy systemd[1]: Started Create Volatile Files and Directories.

[root@freddy ~]# cat /usr/lib/systemd/system/systemd-tmpfiles-setup.service
#  This file is part of systemd.
#
#  systemd is free software; you can redistribute it and/or modify it
#  under the terms of the GNU Lesser General Public License as published by
#  the Free Software Foundation; either version 2.1 of the License, or
#  (at your option) any later version.

[Unit]
Description=Create Volatile Files and Directories
Documentation=man:tmpfiles.d(5) man:systemd-tmpfiles(8)
DefaultDependencies=no
Conflicts=shutdown.target
After=local-fs.target systemd-sysusers.service
Before=sysinit.target shutdown.target
RefuseManualStop=yes

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/bin/systemd-tmpfiles --create --remove --boot --exclude-prefix=/dev

The previous command reads all the configuration files and execute directories' creation/clean up as specified.

Scheduled cleaning

The systemd-tmpfile service execution, at boot time, will ensure that all the required temporary directories are created --- but what about any scheduled clean up?

Systemd gives you the timer unit for controlling scheduled and cyclic actions to be performed in the running system.

To quote the systemd manual:

A unit configuration file whose name ends in ".timer" encodes information about a timer controlled and supervised by systemd, for timer-based activation.

For each timer file, a matching unit file must exist, describing the unit to activate when the timer elapses. By default, a service by the same name as the timer (except for the suffix) is activated. Example: a timer file foo.timer activates a matching service foo.service. The unit to activate may be controlled by Unit=.

You can inspect the behaviour of the timer unit by querying the systemd daemon:

[root@freddy ~]# systemctl status systemd-tmpfiles-clean.timer
● systemd-tmpfiles-clean.timer - Daily Cleanup of Temporary Directories
   Loaded: loaded (/usr/lib/systemd/system/systemd-tmpfiles-clean.timer; static; vendor preset: disabled)
   Active: active (waiting) since Thu 2016-08-18 20:06:04 CEST; 2 weeks 2 days ago
     Docs: man:tmpfiles.d(5)
           man:systemd-tmpfiles(8)

Aug 18 20:06:04 freddy systemd[1]: Started Daily Cleanup of Temporary Directories.

[root@freddy ~]# cat /usr/lib/systemd/system/systemd-tmpfiles-clean.timer
#  This file is part of systemd.
#
#  systemd is free software; you can redistribute it and/or modify it
#  under the terms of the GNU Lesser General Public License as published by
#  the Free Software Foundation; either version 2.1 of the License, or
#  (at your option) any later version.

[Unit]
Description=Daily Cleanup of Temporary Directories
Documentation=man:tmpfiles.d(5) man:systemd-tmpfiles(8)

[Timer]
OnBootSec=15min
OnUnitActiveSec=1d

As you'll find on the timer unit, it will run just 15 minutes after systemd start, and then every 24 hours from that time onward. The command, in this case, will only affect files/directories purging/cleaning.

Configuration files

Let's discuss systemd-tmpfiles configuration files.

Typically, for unix-like services, configuration files are located in different places and they have a hierarchical priority process. The configuration locations for systemd-tmpfiles service have the following order priority (Highest to lower):

  1. /etc/tmpfiles.d/*.conf
  2. /run/tmpfiles.d/*.conf
  3. /usr/lib/tmpfiles.d/*.conf

Supposing that a configuration file with the same name is placed under all the three configuration directories, the file with highest priority will be the one in /etc. The configuration files placed under /run are created at runtime by services/daemons to control temporary directory cleaning processes. And, as usual, configuration files under /usr/lib/* should be never edited directly because they're vendor-provided --- you should override them using this priority mechanism, placing a custom file under /etc/tmpfiles.d/*.

Looking at configuration file syntax, a systemd-tmpfiles configuration contains:

Type, Path, Mode, UID, GID, Age, and Arguments

You can inspect the installed configuration file and understand their behaviour looking at the systemd-tmpfiles man page.

We'll now explore some existing configuration files in the /usr/lib/tmpdfiles.d directory:

Directory creation

[root@freddy ~]# cat /usr/lib/tmpfiles.d/httpd.conf
d /run/httpd 710 root apache
d /run/httpd/htcacheclean 700 apache apache

In this example, systemd will create the /run/httpd and /run/httpd/htcacheclean, if they don't yet exist, assigning them the given permission, UID and GID.

File removal

[root@freddy ~]# cat /usr/lib/tmpfiles.d/rpm.conf
r /var/lib/rpm/__db.*

In this example, systemd will periodically clean up RPM database library files.

Symlink creation and recursive file copy

[root@freddy ~]# cat /usr/lib/tmpfiles.d/etc.conf
#  This file is part of systemd.
#
#  systemd is free software; you can redistribute it and/or modify it
#  under the terms of the GNU Lesser General Public License as published by
#  the Free Software Foundation; either version 2.1 of the License, or
#  (at your option) any later version.

# See tmpfiles.d(5) for details

L /etc/os-release - - - - ../usr/lib/os-release
L /etc/localtime - - - - ../usr/share/zoneinfo/UTC
L+ /etc/mtab - - - - ../proc/self/mounts
C /etc/nsswitch.conf - - - -
C /etc/pam.d - - - -

In this example, systemd will ensure the creation of symbolic links for /etc/os-release, /etc/localtime and /etc/mtab.

If suffixed with '+', and a file already exists where the symlink is to be created, the file will be removed and be replaced by the symlink.

Lastly ,"C" types for files/directories /etc/nsswitch.conf and /etc/pam.d, quoting the tmpfiles.d manual section:

Recursively copy a file or directory, if the destination files or directories do not exist yet. Note that this command will not descend into subdirectories if the destination directory already exists. Instead, the entire copy operation is skipped. If the argument is omitted, files from the source directory /usr/share/factory/ with the same name are copied. Does not follow symlinks.

Time option usage

[root@freddy ~]# cat /usr/lib/tmpfiles.d/cups.conf
# See tmpfiles.d(5) for details

d /run/cups 0755 root lp -
d /run/cups/certs 0511 lp sys -

d /var/spool/cups/tmp - - - 30d

Finally, in this example, you can see the usage of Time options. Each file older than 30 days on /var/spool/cups/tmp will be deleted.

Note that the Time option designates that a file will be considered unused only if atime, mtime and ctime are all older than the specified time.

If you want to dig more on the available configuration types, just type "man 5 tmpfiles.d" on your shell, and in case you want to test just one configuration file at a time, you can place it as an argument to the systemd-tmpfiles command.

Feel free to leave comments or ask questions! Thanks for reading.

Last updated: August 14, 2023