Temporary files and directories are a basic function of almost all operating systems. They store data generated by the operating system and different applications running on it. If not regularly cleaned, these files can take up a large amount of storage space. To avoid disk space issues and possible data leaks, the best practice is to clean up these files regularly. That is where systemd-tmpfiles comes in.
The systemd-tmpfiles services is a configurable tool for managing temporary files and directories. It creates, removes, and cleans up volatile and temporary data that is stored on the system. This article will help you to understand how systemd-tmpfiles functions as it automatically creates, removes, or cleans the temporary files in our system.
Table of Contents
systemd-tmpfiles Unit Files
systemd-tmpfiles is made up of several different unit files. There are four services units which serve different functions, and a single timer unit to schedule cleaning.
- systemd-tmpfiles-setup-dev.service - Creates Static Device Nodes in /dev
- systemd-tmpfiles-setup.service - Creates Volatile Files and Directories
- systemd-tmpfiles-clean.service - Cleanup of Temporary Directories
- systemd-tmpfiles-clean.timer - Timer unit to trigger systemd-tmpfiles-clean.service
The last three unit files above also have user-space counterparts. They can run the service as a non-privileged user. They serve the same purposes, but have some minor differences. Besides the description, the other main differences are:
- The system service unit and the user service unit execute at different targets. The system unit executes after local-fs.target and time-set.target, but before shutdown.target. Where the user target starts before basic.target and shutdown.target.
- The ExecStart line adds the
--user
designation in the command to specify it is running in the user-space.
Let's take a closer look at each of these services and timer units. Remember, the functions are the same whether is a system service unit or a user service unit.
Create Static Device Nodes - Systemd-tmpfiles-setup-dev.service
This part of the service is rarely interacted with unless you are working on specific hardware or device driver development. Therefore, we will just touch on the subject and move on.
Every device that interacts with the operating system must have a software name. This is usually referred to as a device special file, or device node. These device nodes are stored in the /dev
directory. The systemd-tmpfiles-setup-dev.service creates some of these device special files, or device nodes, on boot. It does this by specifying the --prefix=/dev
option when executing systemd-tmpfiles
.
ExecStart=/usr/bin/systemd-tmpfiles --prefix=/dev --create --boot
Creating and Removing Temp Files at Boot - Systemd-tmpfiles-setup.service
When a system running systemd boots, the systemd-tmpfiles-setup is one of the first units started. This unit runs a command which creates and removes the directories and files designated in it's configuration.
ExecStart=/usr/bin/systemd-tmpfiles --create --remove --boot --exclude-prefix=/dev
The --boot
ensures that it executes actions that are marked to be run at boot. This service explicitly excludes anything with the /dev
prefix.
Scheduled Cleanup of Temporary Files and Directories - systemd-tmpfiles-clean.service
The systemd-tmpfiles-clean.service is the service that runs at scheduled times. A timer unit of the same name controls when it executes. It executes systemd-tmpfiles with only the --clean
option.
ExecStart=systemd-tmpfiles --clean
When the --clean
option is passed, all files and directories with an age field specified will be cleaned.
Timer Unit to Trigger Scheduled Cleanups - systemd-tmpfiles-clean.timer
We discussed creating systemd timer units in a past article called "Using systemd Timer Units to Schedule Jobs". A systemd timer unit is a configuration file that is used to activate a service unit of the same name. Likewise, the systemd-tmpfiles-clean.timer unit triggers the systemd-tmpfiles-clean.service unit as specified intervals. The default configuration schedules the timer to trigger at 15 minutes after boot, and once a day while the system is running.
[Timer]
OnBootSec=15min
OnUnitActiveSec=1d
OnBootSec - Defines the time relative to when the machine boooted.
OnUnitActiveSec - Defines the timer relative to the last service unit activation.
For more in-depth information about timer units and their starting point, see the resources section below.
You can check the time left on the timer. For example, the below output shows that the systemd-tmpfiles-clean.timer will trigger again in 18 hours.
systemd-tmpfiles Configuration Files
The configuration for systemd-tmpfiles is made up of many different files. A single file is typically generated for each service or application. The systemd-tmpfiles checks the following locations for configuration files:
- /etc/tmpfiles.d/*.conf
- /run/tmpfiles.d/*.conf
- /usr/lib/tmpfiles.d/*.conf
Files stored in the above directories are used to set the configuration for the systemd-tmpfiles. Files placed in the /etc/tmpfiles.d/
directory have the highest priority. The /run/tmpfiles.d/
directory has the second highest priority, with /usr/lib/tempfiles.d
having the lowest priority. If a file with the same name was placed in all three directories, the file in /etc/tmpfiles.d/ would take precedence over the others.
Additionally, user specific configurations can be stored in:
- ~/.config/user-tmpfiles.d/*.conf
- $XDG_RUNTIME_DIR/user-tmpfiles.d/*.conf
- ~/.local/share/user-tmpfiles.d/*.conf
Configuration Syntax
All of the systemd-tmpfiles follow the same syntax. The format is one line per path (file or directory) which consists of seven fields.
- Type - Consists of a single letter and optional special character (!, -, or +) that tells systemd-tmpfiles which action to take.
- Path - File system path specification for the target file or directory.
- Mode - The mode or permissions of target file in binary representation.
- User - The user to use for target file
- Group - The group to use for target file
- Age - Date field used to determine if a file should be acted upon.
- Argument - Serves different functions depending on what type is set.
This is of course a simplified explanation of each field. For more in-depth information see the resources section below. We will discuss some of the more common types, age uses and arguments below in the examples section.
Here is an example configuration file placed in ~/.config/tmpfiles.d/
:
[savona@putor tmpfiles.d]$ cat myscript.conf
d /tmp/myscript 700 savona savona 1h
Manually Running systemd-tmpfiles Configurations
All configuration files (system or user) are checked when the service units run. However, you can run all or one of the configurations manually with the systemd-tmpfiles binary.
To manually run all system configurations invoke the systemd-tmpfiles
command with the desired action(s). For example to run a remove:
sudo systemd-tmpfiles --remove
or
sudo systemd-tmpfiles --clean --remove --create
NOTE: You will have to use sudo
or elevate to root to run system configurations.
You can run systemd-tmpfiles against a specific configuration file by passing it as an argument to the end of the command. For example, this would run the dns.conf
file only:
$ sudo systemd-tmpfiles --remove /usr/lib/tmpfiles.d/dnf.conf
To run user-space configurations you will need to add the --user
option like so:
systemd-tmpfiles --user --remove ~/.config/user-tmpfiles.d/delete-chrome-cache.conf
Examples of Managing Temporary Files with systemd-tmpfiles
Now that we know all the parts involved in systemd-tmpfiles, let's see some examples. Below are examples of system level uses, followed by user-space specific examples.
Real World System Services Examples
Example 1: Create Directory and Set It's Permissions at Boot
OpenSSH requires the directory /var/empty/sshd
to be present, owned by root, and not world writable. If it is not, the service will fail to start with the following error.
sshd[12861]: Missing privilege separation directory: /var/empty/sshd
The following systemd-tmpfiles configuration ensures the directory exists and has the correct permissions.
[savona@putor tmpfiles.d]$ cat openssh.conf
d /var/empty/sshd 711 root root -
The d
type specifies that the file should be created and cleaned up. The next field is the path, then the mode and user/group specifications. The last - means that this configuration file does not specify an age, which means no automatic cleanup will occur.
Example 2: Remove a File If It Exists At Boot
The DNF Package Manager uses a systemd-tmpfiles configuration to remove files during boot.
[savona@putor tmpfiles.d]$ cat dnf.conf
# Unlink the dnf lock files during boot
R /var/tmp/dnf*/locks/*
r /var/cache/dnf/download_lock.pid
r /var/cache/dnf/metadata_lock.pid
r /var/lib/dnf/rpmdb_lock.pid
The capital R
type recursively removes the path and it's subdirectories. The lowercase r
type is a simple remove of the file or empty directory. The next field is the path to me acted upon. There are no permissions or age requirements for these types.
Example 3: Create Then Clean Up Directories Based On Time
In this example the system creates and cleans up the basic /tmp
and /var/tmp
directories.
[savona@putor tmpfiles.d]$ cat tmp.conf
q /tmp 1777 root root 10d
q /var/tmp 1777 root root 30d
The q
tells the system to create a subvolume or directory. The 10d
we see in the age field tells systemd-tmpfiles when it should be cleaned. In this case files that have ages past 10 days will be cleaned from the /tmp
directory. Files aged past 30 days will be cleaned from the /var/tmp
directory.
The date field, when set, is used to decide what files to delete when cleaning. If a file or directory is older than the current time minus the age field, it is deleted.
tmpfiles.d Man Page
The age field is more complex than I can cover here. For a more in-depth look at aging, see the tmpfiles.d man page linked in the resources section.
Example 4: Set MOTD to Display Hostname and Boot ID
Okay, so this may not be so "real world", but it's interesting. It also gives us a chance to look at the dynamic specifiers. These specifiers allow you to insert dynamic content into the path and argument fields. Let's take a loot at the example.
[savona@putor ~]$ cat /etc/tmpfiles.d/motd.conf
r! /etc/motd
f! /etc/motd - - - - Hello and Welcome to %H The boot ID is %b
In the file above we are using !
to specify that these should be ran at boot. The first line starts with r!
which says remove the path at boot. The second line starts with f!
which creates the new MOTD file. The string in the arguments field specifies what the file content should be. The end result is the /etc/motd
file being replaced with a new one. The file file contains the specifiers %H
for hostname, and %b
for boot id. Here is the new MOTD file in action:
[email protected]'s password:
Hello and Welcome to putor The boot ID is 04cd5672cc27482680787ee4a028062b
Last login: Tue May 12 20:58:26 2020
[savona@putor ~]$
User Specific Examples
Example 1: Deleting Google Chrome Cache at Shutdown
This is a very user-centric example, although probably not a very practical one. In this example, we will setup a configuration file to empty the Google Chrome Cache directory using the user-space systemd-tmpfiles-setup.service.
First we create the configuration directory:
mkdir ~/.config/user-tmpfiles.d
Then we create a file inside that directory named delete-google-cach.conf
with the following contents.
R %h/.cache/google-chrome/Default/Cache/*
The R
specifies to recursively remove files from the specified path. The systemd-tmpfiles-setup.service will empty the directory when it runs. We can test it by using the same command that is on the ExecStart line of the unit file.
[savona@putor ~]$ ls -lrt ~/.cache/google-chrome/Default/Cache/
total 27744
drwx------. 2 savona savona 4096 May 12 01:40 index-dir
-rw-------. 1 savona savona 5305 May 12 01:40 079a095ca14f7de9_0
-rw-------. 1 savona savona 8781 May 12 01:40 9a9531f2902f4d8b_0
-rw-------. 1 savona savona 71209 May 12 01:40 acb291bff88b882a_0
[savona@putor ~]$ systemd-tmpfiles --user --create --remove --boot
[savona@putor ~]$ ls -lrt ~/.cache/google-chrome/Default/Cache/
total 0
Example 2: Create and Cleanup a Share Directory
I have a shared directory that my colleagues use to store large files. These files are usually drafts and no finish works are every put in this directory. It sometimes gets rather large. I created a systemd-tmpfiles confguration to ensure the creation of the directory, permissions are set, and a cleanup runs every month.
[savona@putor user-tmpfiles.d]$ cat clean-share.conf
d /home/putorius 760 savona putorius 4w
Conclusion
In this article we discusses the service and path units that make up the systemd-tmpfiles suite. We also covered the configuration files and looked at some examples of it's use in real world.
This started out as a primer on systemd-tmpfiles, but I think I got a little long winded. If you have any comments or suggestion I would love to hear them in the comments below.
Resources & Further Learning
Leave a Reply Cancel reply
This site uses Akismet to reduce spam. Learn how your comment data is processed.
2 Comments
Join Our Newsletter
Categories
- Bash Scripting (17)
- Basic Commands (51)
- Featured (7)
- Just for Fun (5)
- Linux Quick Tips (98)
- Linux Tutorials (65)
- Miscellaneous (15)
- Network Tools (6)
- Reviews (2)
- Security (32)
Great article, thanks.
Are you sure the "*" is necessary on the end of
R %h/.cache/google-chrome/Default/Cache/*
?? It seems redundant