我有以下日志旋转脚本
/path/to/folder {
daily
rotate 30
notifempty
sharedscripts
copytruncate
compress
dateext
preremove
if file --mime-type "$1" | grep -q gzip$; then
mkdir -p /path/to/archive/folder && cp $1 $_
fi
endscript
}
我正在努力实现的目标:-
在保留 30 天后删除日志文件之前,请复制到另一个文件夹。
我在调试模式下运行此日志存储配置
logrotate -d $CONFIG_FILE
从日志的外观来看,轮换工作正常,但它甚至没有运行preremove
脚本。 我还没有在实时上运行这个配置,因为我想在这样做之前对其进行测试。
日志旋转版本 3.8.6
我不确定您是在问为什么 preremove 没有运行,或者您的脚本看起来是否正常。
预移除以及如何测试
我不相信 logrotate 如果不删除文件(每-d
),它会运行preremove
脚本。我设置了一个测试用例并在strace
下运行它。logrotate -d
找到了需要删除的文件,并写道它会删除它们,但没有运行preremove
代码。老实说,这对我来说是有道理的,也是我所期望的,因为preremove
可能会像删除本身一样具有破坏性。
要执行测试,我认为您需要在另一个目录中重现您的实时环境并实际运行它。不要使用全尺寸文件,只需使用几行的虚拟文件。创建一个脚本来生成测试文件夹,以便可以轻松重现测试。使用touch
设置时间戳。例如:
for n in $(seq 1 30); do
cp test.log test.log.$n
gzip test.log.$n
touch -d "now - $n day" test.log.$n.gz
done
脚本本身
grep -q gzip$
错了。$
将在外壳解析中消失。您需要将其括在单引号中。- 正如其他人所写,我不希望
$_
起作用。重复目录名称,或在脚本中使用变量。 - 我认为您不需要像建议的那样在 EOL 进行
逃逸。
- 你可能想要
cp -p
,正如有人建议的那样。 - 如果您的文件很大,则
cp
会很慢。如果您的归档位于同一文件系统上,请考虑改用ln
(而不是ln -s
!这将是即时的。 - 使用
file --mime-type
可能工作正常,但坦率地说,在这种情况下,我只是基于文件名,因为 logrotate 会可靠地将.gz
附加到file
将返回gzip
的任何文件上。expr "$1" : '.*gz$'
将给出一个非零数作为以.gz
结尾的任何$1
的标准输出。它将为不以.gz
结尾的文件名提供准确的数字 0 作为标准输出。
我认为您的条件本身并没有实现,您可以将 echo 放在预删除之前进行调试。尝试手动执行您的 if 条件并查看。
# file --mime-type * | grep -i *.1
audit.log.1: text/plain
# file --mime-type * | grep -i *.1$
# file --mime-type * | grep -q *.1$
# file --mime-type * | grep -q *.1
您可能缺少行继续转义,如某些示例中所示
preremove
# debug line
systemd-cat -t "rot-pre-rm" echo "preremove block, file: $1"
if file --mime-type "$1" | grep -q gzip$; then
cp -p "$1" /path/to/archive/syslog/;
fi;
endscript