tmpfiles: extend "Age" to accept an "age-by" argument
For "systemd-tmpfiles --cleanup", when the "Age" parameter
is specified, the criteria for deletion is determined from
the path's last modification timestamp ("mtime"), its last
access timestamp ("atime") and its last status change
timestamp ("ctime").
For instance, if one of those paths to be cleaned up are
opened, it results in the modification of "atime", which
results file system entry to not be removed because the
default aging algorithm would skip the entry.
Add an optional "age-by" argument by extending the "Age"
parameter to restrict the clean-up for a particular type
of file timestamp, which can be specified in "tmpfiles.d"
as follows:
[age-by:]cleanup-age, where age-by is "[abcmACBM]+"
For example:
d /foo/bar - - - abM:1m -
Would clean-up any files that were not accessed and created,
or directories that were not modified less than a minute ago
in "/foo/bar".
Fixes: #17002
This commit is contained in:
committed by
Lennart Poettering
parent
66973219c0
commit
7f7a50dd15
Executable
+196
@@ -0,0 +1,196 @@
|
||||
#! /bin/bash
|
||||
|
||||
# Test the "Age" parameter (with age-by) for systemd-tmpfiles.
|
||||
|
||||
set -e
|
||||
set -x
|
||||
|
||||
# Test directory structure looks like this:
|
||||
# /tmp/ageby/
|
||||
# ├── d1
|
||||
# │ ├── f1
|
||||
# │ ├── f2
|
||||
# │ ├── f3
|
||||
# │ └── f4
|
||||
# ├── d2
|
||||
# │ ├── f1
|
||||
# │ ├── f2
|
||||
# ...
|
||||
|
||||
export SYSTEMD_LOG_LEVEL="debug"
|
||||
|
||||
rm -rf /tmp/ageby
|
||||
mkdir -p /tmp/ageby/d{1..4}
|
||||
|
||||
# TODO: There is probably a better way to figure this out.
|
||||
# Test for [bB] age-by arguments only on filesystems that expose
|
||||
# the creation time. Note that this is _not_ an accurate way to
|
||||
# check if the filesystem or kernel version don't provide the
|
||||
# timestamp. But, if the timestamp is visible in "stat" it is a
|
||||
# good indicator that the test can be run.
|
||||
TEST_TMPFILES_AGEBY_BTIME=${TEST_TMPFILES_AGEBY_BTIME:-0}
|
||||
if stat --format "%w" /tmp/ageby 2>/dev/null | grep -qv '^[\?\-]$'; then
|
||||
TEST_TMPFILES_AGEBY_BTIME=1
|
||||
fi
|
||||
|
||||
touch -a --date "2 minutes ago" /tmp/ageby/d1/f1
|
||||
touch -m --date "4 minutes ago" /tmp/ageby/d2/f1
|
||||
|
||||
# Create a bunch of other files.
|
||||
touch /tmp/ageby/d{1,2}/f{2..4}
|
||||
|
||||
# For "ctime".
|
||||
touch /tmp/ageby/d3/f1
|
||||
chmod +x /tmp/ageby/d3/f1
|
||||
sleep 1
|
||||
|
||||
# For "btime".
|
||||
touch /tmp/ageby/d4/f1
|
||||
sleep 1
|
||||
|
||||
# More files with recent "{a,b}time" values.
|
||||
touch /tmp/ageby/d{3,4}/f{2..4}
|
||||
|
||||
# Check for cleanup of "f1" in each of "/tmp/d{1..4}".
|
||||
systemd-tmpfiles --clean - <<-EOF
|
||||
d /tmp/ageby/d1 - - - a:1m -
|
||||
e /tmp/ageby/d2 - - - m:3m -
|
||||
D /tmp/ageby/d3 - - - c:2s -
|
||||
EOF
|
||||
|
||||
for d in d{1..3}; do
|
||||
test ! -f "/tmp/ageby/${d}/f1"
|
||||
done
|
||||
|
||||
if [[ $TEST_TMPFILES_AGEBY_BTIME -gt 0 ]]; then
|
||||
systemd-tmpfiles --clean - <<-EOF
|
||||
d /tmp/ageby/d4 - - - b:1s -
|
||||
EOF
|
||||
|
||||
test ! -f "/tmp/ageby/d4/f1"
|
||||
else
|
||||
# Remove the file manually.
|
||||
rm "/tmp/ageby/d4/f1"
|
||||
fi
|
||||
|
||||
# Check for an invalid "age" and "age-by" arguments.
|
||||
for a in ':' ':1s' '2:1h' 'nope:42h' '" :7m"' 'm:' '::' '"+r^w-x:2/h"' 'b ar::64'; do
|
||||
systemd-tmpfiles --clean - <<EOF 2>&1 | grep -q -F 'Invalid age'
|
||||
d /tmp/ageby - - - ${a} -
|
||||
EOF
|
||||
done
|
||||
|
||||
for d in d{1..4}; do
|
||||
for f in f{2..4}; do
|
||||
test -f "/tmp/ageby/${d}/${f}"
|
||||
done
|
||||
done
|
||||
|
||||
# Check for parsing with whitespace, repeated values
|
||||
# for "age-by" (valid arguments).
|
||||
for a in '" a:24h"' 'cccaab:2h' '" aa : 4h"' '" a A B C c:1h"'; do
|
||||
systemd-tmpfiles --clean - <<EOF
|
||||
d /tmp/ageby - - - ${a} -
|
||||
EOF
|
||||
done
|
||||
|
||||
for d in d{1..4}; do
|
||||
for f in f{2..4}; do
|
||||
test -f "/tmp/ageby/${d}/${f}"
|
||||
done
|
||||
done
|
||||
|
||||
# Check that all files are removed if the "Age" is
|
||||
# set to "0" (regardless of "age-by" argument).
|
||||
systemd-tmpfiles --clean - <<-EOF
|
||||
d /tmp/ageby/d1 - - - abc:0 -
|
||||
e /tmp/ageby/d2 - - - cmb:0 -
|
||||
EOF
|
||||
|
||||
for d in d{1,2}; do
|
||||
for f in f{2..4}; do
|
||||
test ! -f "/tmp/ageby/${d}/${f}"
|
||||
done
|
||||
done
|
||||
|
||||
# Check for combinations:
|
||||
# - "/tmp/ageby/d3/f2" has file timestamps that
|
||||
# are older than the specified age, it will be
|
||||
# removed
|
||||
# - "/tmp/ageby/d4/f2", has not aged for the given
|
||||
# timestamp combination, it will not be removed
|
||||
touch -a -m --date "4 minutes ago" /tmp/ageby/d3/f2
|
||||
touch -a -m --date "8 minutes ago" /tmp/ageby/d4/f2
|
||||
systemd-tmpfiles --clean - <<-EOF
|
||||
e /tmp/ageby/d3 - - - am:3m -
|
||||
D /tmp/ageby/d4 - - - mc:7m -
|
||||
EOF
|
||||
|
||||
test ! -f "/tmp/ageby/d3/f2"
|
||||
test -f "/tmp/ageby/d4/f2"
|
||||
|
||||
# Check that all files are removed if only "Age" is set to 0.
|
||||
systemd-tmpfiles --clean - <<-EOF
|
||||
e /tmp/ageby/d3 - - - 0s
|
||||
d /tmp/ageby/d4 - - - 0s
|
||||
EOF
|
||||
|
||||
for d in d{3,4}; do
|
||||
for f in f{2..4}; do
|
||||
test ! -f "/tmp/ageby/$d/${f}"
|
||||
done
|
||||
done
|
||||
|
||||
# Check "age-by" argument for sub-directories in "/tmp/ageby".
|
||||
systemd-tmpfiles --clean - <<-EOF
|
||||
d /tmp/ageby/ - - - A:1m -
|
||||
EOF
|
||||
|
||||
for d in d{1..4}; do
|
||||
test -d "/tmp/ageby/${d}"
|
||||
done
|
||||
|
||||
# Check for combinations.
|
||||
touch -a -m --date "5 seconds ago" /tmp/ageby/d{1,2}
|
||||
systemd-tmpfiles --clean - <<-EOF
|
||||
e /tmp/ageby/ - - - AM:4s -
|
||||
EOF
|
||||
|
||||
for d in d{1,2}; do
|
||||
test ! -d "/tmp/ageby/${d}"
|
||||
done
|
||||
|
||||
for d in d{3,4}; do
|
||||
test -d "/tmp/ageby/${d}"
|
||||
done
|
||||
|
||||
# Check "btime" for directories.
|
||||
if [[ $TEST_TMPFILES_AGEBY_BTIME -gt 0 ]]; then
|
||||
systemd-tmpfiles --clean - <<-EOF
|
||||
d /tmp/ageby/ - - - B:8s -
|
||||
EOF
|
||||
|
||||
for d in d{3,4}; do
|
||||
test -d "/tmp/ageby/${d}"
|
||||
done
|
||||
fi
|
||||
|
||||
# To bump "atime".
|
||||
touch -a --date "1 second ago" /tmp/ageby/d3
|
||||
systemd-tmpfiles --clean - <<-EOF
|
||||
d /tmp/ageby/ - - - A:2s -
|
||||
EOF
|
||||
|
||||
test -d /tmp/ageby/d3
|
||||
test ! -d /tmp/ageby/d4
|
||||
|
||||
# Check if sub-directories are removed regardless
|
||||
# of "age-by", when "Age" is set to "0".
|
||||
systemd-tmpfiles --clean - <<-EOF
|
||||
D /tmp/ageby/ - - - AM:0 -
|
||||
EOF
|
||||
|
||||
test ! -d /tmp/ageby/d3
|
||||
|
||||
# Cleanup the test directory (fail if not empty).
|
||||
rmdir /tmp/ageby
|
||||
Reference in New Issue
Block a user