Using a systemd service to create a file

Elliot asked:

I am trying to create a systemd service to clear a directory of old files automatically. If l were to do this manually, l would be using a pair of commands like

$ /usr/bin/touch -t $(/usr/bin/date -d'-7day' +%Y%m%d%H%M) /tmp/cutoff
$ /usr/bin/find /path/to/dir ! -newer /tmp/cutoff -exec rm {} \;

The former line does in fact generate the placeholder file in the /tmp directory. However, the following service definition

Description=Cleanup index cache left behind by bup backup

ExecStart=/usr/bin/touch -t $(/usr/bin/date -d'-7day' +%%Y%%m%%d%%H%%M) /tmp/cutoff

Fails to generate the place-holder

$ /usr/bin/touch -t $(/usr/bin/date -d'-7day' +%Y%m%d%H%M) /tmp/cutoff
$ ls -l /tmp/cutoff
-rw-r--r--. 1 user group 0 Mar 20 14:36 /tmp/cutoff
$ rm /tmp/cutoff
$ sudo systemctl start cleanup_index_cache
$ ls -l /tmp/cutoff
ls: cannot access '/tmp/cutoff': No such file or directory
$ sudo systemctl start cleanup.service
$ ls -l /tmp/cutoff

If there is a way to delete files/directories older than a certain age using systemd? Is there something l’m missing in just transcribing shell commands to systemd directives?

My answer:

systemd does not send commands in ExecStart= and its relatives through the shell. It executes them directly. So you cannot use shell constructs such as $().

It’s not clear why you’re generating a date and touching a file with it anyway. find is perfectly capable of finding files older than a certain time on its own.

From the man page:

       -mtime n
              File's  data was last modified n*24 hours ago.  See the comments
              for -atime to understand how rounding affects the interpretation
              of file modification times.

That bit explains:

       -atime n
              File  was  last  accessed n*24 hours ago.  When find figures out
              how many 24-hour periods ago the file  was  last  accessed,  any
              fractional part is ignored, so to match -atime +1, a file has to
              have been accessed at least two days ago.

find is also capable of deleting files on its own and does not need to call out to rm (and it’s potentially a bad idea to do so for a variety of reasons).

              Delete files; true if removal succeeded.  If the removal failed,
              an  error message is issued.  If -delete fails, find's exit sta‐
              tus will be nonzero (when it eventually exits).  Use of  -delete
              automatically turns on the `-depth' option.

              Warnings:  Don't  forget that the find command line is evaluated
              as an expression, so putting -delete first will make find try to
              delete everything below the starting points you specified.  When
              testing a find command line that you later intend  to  use  with
              -delete,  you should explicitly specify -depth in order to avoid
              later surprises.  Because -delete  implies  -depth,  you  cannot
              usefully use -prune and -delete together.

So to delete files older than 7 days, you can simply run find directly, with no other funny stuff:

/usr/bin/find /directory -mtime +6 -delete

View the full question and any other answers on Server Fault.

Creative Commons License
This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.