我有一个目录,其中包含多个目录,每个目录都包含日志文件。每个日志文件都以YYYY-MM-DD.log 的格式命名。所以它将是 /path/to/logs/tokyo/2017-06-29.log、/path/to/logs/london/2017-06-29.log 等。
每天午夜都会以新日期打开一个新日志,而旧日志将永远不会被再次写入。
事实上,这些日志有数千个,可以追溯到几年前,虽然它们只是文本文件,但它们开始占用不可忽略的空间。所以我想做的是编写一个脚本来查找所有这些日志目录,找到今天之前的任何日志目录,并对它们进行 bzip 压缩。这是我到目前为止所拥有的:
#!/bin/sh
LOGDATE=$(date +%Y-%m-%d)
LOGPATH="/path/to/logs"
for i in $(ls $LOGPATH/*/*.log); do
if [ "$i" != "$LOGDATE.log" ];then
tar cfjv $i.tar.bz2 $i
rm $i
else
fi
done
我遇到了两个问题。首先,for 循环中的 $(ls ...) 出错,表示参数列表太长。其次,在 tar 语句中,我希望 bzipped 输出文件位于日志文件所在的目录中,但似乎将它们放在运行脚本的目录中,并且我找不到方法使循环对其遇到的每个匹配文件使用正确的目录。
想必使用编写良好的 find 和 xargs 命令可以更好地处理这个问题,但我一直无法找到一个可以完成我需要它做的事情的命令。
该脚本的最终目标是找到日志目录结构中的所有日志文件,检查它是否不是今天的日志,将其压缩到位,然后删除文本日志。它将立即运行一次以处理所有旧日志,然后添加到 crontab 中以每天午夜过后运行。
我需要做什么来纠正我的脚本?或者,有更好的方法吗?
唯一真正的限制是它是一个 freebsd 服务器,因此它需要使用 sh 或 csh,并使用 freebsd 工具(意味着例如 bsd 的 find 而不是 GNU find,后者具有更广泛的选项)。
答案1
find
如果您只压缩一个文件,则无需制作 tarball,这一事实可以使这一过程变得更加简单:
find $LOGPATH/ -name \*.log -mtime 1 -execdir bzip2 "{}" \;
如果您find
没有-mtime
,您可以通过使用touch
创建一个$DATEFILE
具有特定最后修改时间(例如“今天午夜”)的文件(例如 )来伪造它,然后使用:
find $LOGPATH/ -name \*.log -not -newer /path/to/$DATEFILE -execdir bzip2 "{}" \;
rm /path/to/"$DATEFILE"
答案2
当然,最简单的方法是利用 FreeBSD 已有的工具 - newsyslog
。
创建一个/etc/newsyslog.conf
文件,或编辑现有文件。您给出文件的名称(您可以使用通配符,尽管不同的目录可能需要多行),您想要保留多少份副本(在您的情况下是一个非常大的数字),何时滚动文件(有一个标志允许您自己执行此操作),您想要使用哪个压缩系统等。
用于newsyslog -FvC path-to-your-log-file
第一次启动。
顺便说一句,您可以将相关行放入
/usr/local/etc/newsyslog.conf.d
, 中,以您喜欢的任何名称命名。这使得升级后更容易记住它。