10

I have the following configuration to clean up temporary files (default for CentOS 7), which says that files in /tmp should be removed if they are more than 10 days old.

[root]# tail -n +10 /usr/lib/tmpfiles.d/tmp.conf | head -n 3
# Clear tmp directories separately, to make them easier to override
d /tmp 1777 root root 10d
d /var/tmp 1777 root root 30d

However, even after running systemd-tmpfiles --clean, when I look at the contents of /tmp, there are files in there that are more than 10 days old.

[root]# ls -dl /tmp/backup-inspection
drwxr-xr-x 8 root root 68 Aug 29  2014 /tmp/backup-inspection

The contents of the /tmp directory is huge:

[root]# du -h /tmp | tail -n 1
3.5G    /tmp

Can anyone explain to me why the backup-inspection directory is not removed? It is nearly 1 year old?

4
  • It probably isn't a systemd tmpfile. Not everything in /tmp is, any application can create files in /tmp
    – jordanm
    Aug 3, 2015 at 4:11
  • I didn't think it mattered who created the file in the /tmp directory. E.g., if I write an application that writes to /tmp, should the tempfiles daemon delete it regardless of who created it?
    – magnus
    Aug 3, 2015 at 4:51
  • Quick addition: It does not matter, at least if you use the e flag.
    – Thorian93
    Aug 10, 2020 at 11:32

4 Answers 4

14

I have run into the same problem recently and found this question, so i am sharing my experience.

Actually systemd-tmpfiles has full support for recursive directory tree processing as you would expect (the other answer confused me enough to check the source code). The reason files was not deleted (in my case) was atime. systemd-tmpfiles checks ctime (except for directories), mtime and atime and all three (or two) of them must be old enough for the file (or directory) to be deleted.

Actually there may be other reasons, because systemd-tmpfiles has a lot of internal rules for skipping files. To find out why some files are not deleted, run systemd-tmpfiles as following:

env SYSTEMD_LOG_LEVEL=debug systemd-tmpfiles --clean

It will probably dump a lot of output into your console. Note that if you try to redirect stdout to e.g. a file, output disappears and is sent to systemd journal (so that it can be obtained via e.g. journalctl). In my case the output was also cut in the middle (or i just do not know how to use journalctl), so my solution was to temporarily increase history buffer in my terminal emulator.

10

I've been going to great lengths lately to solve similar issues on servers under my purview.

The simple answer is basically just: systemd-tmpfiles --clean is a hot mess and you should look into alternatives

The less simple answer is a bit long.

systemd-tmpfiles performs a variety of tasks, but its main one is unrelated to the --clean option: ensuring that the state of your system is appropriately 'reset' upon reboots. That is to say, it ensures that directories and files which need to exist for various reasons are created, and ones which should not exist are removed (along with a long list of relatively esoteric things like creating filesystem subvolumes and quotas, block devices, etc., changing permissions, SELinux attributes, etc. See the manpage if you're curious about everything). These tasks are performed by systemd-tmpfiles --create (for most things) and systemd-tmpfiles --remove (for removing files and directories). These two subcommands consider, roughly, the start of each configuration line: the first field is the type of action, the second the target, the third the mode, etc. Generally, something like systemd-tmpfiles --create --remove is run shortly after boot of the system, before anything that might depend on the actions it takes. One important thing to note is that these actions don't ever look at the fifth argument, the Age parameter. That's where --clean comes in.

systemd-tmpfiles --clean essentially piggybacks on top of this infrastructure by way of a single added field: the Age field. It only considers a few of the particular types of actions the other subcommands do, though: d, D, v, q, Q, C, and also x and X (which only exist to exclude specific things from its cleanup). The ones of these that are relevant to normal use cases are just d and D, though, used for directories, creating-if-doesn't-exist and creating-if-doesn't-exist-or-emptying-if-it-does, respectively. With the ages marked, systemd-tmpfiles --clean will remove the listed path when the age is older than configured.

Here's the catch: it really means the listed path only - the age marking is not recursively applied to the contents of the folder. This means that the configuration lines in your question will only ever remove the entirety of /tmp or /var/tmp, and only if nothing has happened within them for 10 or 30 days, respectively. To make things worse, none of the things which affect the age support globs except for x and X, which are for excluding things from cleanup.

The tmpfiles.d manpage does list one interesting thing which may work for your case if you're lucky: "If the age field starts with a tilde character "~", the clean-up is only applied to files and directories one level inside the directory specified, but not the files and directories immediately inside it." -- for my case, the cleanup needed to happen two levels below /tmp, so there was no way to use this to good effect.

Look into other solutions for cleaning up the contents of your /tmp directory which consider it their primary purpose, rather than being tacked-on the end like systemd-tmpfiles --clean is.

2
  • 1
    This is an older question now, but I ended up using tmpwatch which worked beautifully the first time around. I simply added it to cron's daily schedule. Easy to configure, easy to use. Very different to systemd, which tries to do too much.
    – magnus
    Feb 22, 2016 at 4:07
  • tmpwatch is quite nice, but it not in the SLES default repos. For me the trick was to give the persmissions when trying to clean up a directory. Not sure if that is by design, the documentation reads otherwise.
    – Thorian93
    Aug 10, 2020 at 11:34
1
  • d is for creating directories
  • r is for removing files

From tempfiles.d(5). You don't need the other stuff, try:

d /tmp      1d

   d
       Create a directory if it does not exist yet.

   D
       Create or empty a directory.
r
       Remove a file or directory if it exists. This may not be used to
       remove non-empty directories, use R for that. Lines of this type
       accept shell-style globs in place of normal path names. Does not
       follow symlinks.

   R
       Recursively remove a path and all its subdirectories (if it is a
       directory). Lines of this type accept shell-style globs in place
       of normal path names. Does not follow symlinks.
2
  • Don't forget to run #systemctl enable systemd-tmpfiles #systemctl start systemd-tmpfiles #systemd-tempfiles --clean
    – mac
    Oct 18, 2015 at 21:12
  • Except the removal of files and directories based on age does not work for the "r" action, but works for "d" (and a few others.)
    – bolind
    Mar 11, 2022 at 8:30
0

I also struggled with this for far longer that it should have taken.

My case was that I have a custom tmp directory (needed for a custom application, placed on a fast-ish SSD disk) that needed cleaned of files that had sat unused for seven days.

What I ended up doing was creating a file in /etc/tmpfiles.d called 'foo.conf', with the following line:

d /foo/tmp - - - 7d

What this does (I hope) is:

  1. Delete files and directories under /foo/tmp where atime, mtime and ctime are all older than 7 days.
  2. Don't delete contents in case of reboot.
  3. Create the directory if it doesn't exist (it always will.)
  4. Don't change ownership and permissions on the directory (Mode, UID and GID are all set to -)

I think it's very confusing that r isn't used to remove files due to age. From the man page:

The age field only applies to lines starting with d, D, e, v, q, Q, C, x and X.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .