我最近提出了这样一种情况:一旦超过一定大小,我需要修剪一些相当大的日志文件。除了每个文件中的最后1000行之外的所有内容都被处理掉,作业每隔半小时由cron运行一次。我的解决方案是简单地浏览文件列表,检查大小并在必要时修剪。
for $file (@fileList) {
if ( ((-s $file) / (1024 * 1024)) > $CSize) {
open FH, "$file" or die "Cannot open ${file}: $!\n";
$lineNo = 0;
my @tLines;
while(<FH>) {
push @tLines, $_;
shift @tLines if ++$lineNo < CLLimit;
}
close FH;
open FH, ">$file" or die "Cannot write to ${file}: $!\n";
print FH @tLines;
close FH;
}
这在当前形式下工作,但是对于大型日志文件(尤其是具有100_000 +行的文件)存在大量开销,因为需要读取每一行并在必要时进行移位。
我是否有办法只阅读文件的一部分,例如在这种情况下,我希望只能访问最后的“CLLimit”行。由于脚本部署在一个看起来更好日子的系统上(想想Celeron 700MHz带有64MB RAM),我正在寻找使用Perl的更快的替代方案。
答案 0 :(得分:8)
我意识到你想要使用Perl,但如果这是一个UNIX系统,为什么不使用“tail”实用程序进行修剪呢?您可以使用非常简单的脚本在BASH中执行此操作:
if [ `stat -f "%z" "$file"` -gt "$MAX_FILE_SIZE" ]; then
tail -1000 $file > $file.tmp
#copy and then rm to avoid inode problems
cp $file.tmp $file
rm $file.tmp
fi
话虽如此,如果您为此设置使用Perl,您可能会发现this post非常有帮助。
答案 1 :(得分:4)
估算日志中一条线的平均长度 - 称之为N字节。
从文件末尾向后搜索1000 * 1.10 * N(因子1.10中的误差率为10%)。从那里向前看,只保留最近的1000行。
问的问题是 - 哪个功能或模块?
内置函数seek在我看来就像使用的工具一样?
答案 2 :(得分:4)
考虑简单地使用logrotate实用程序;它包含在大多数现代Linux发行版中。 BSD系统的相关工具称为newsyslog。这些工具的设计或多或少都符合您的预期目的:它以原子方式将日志文件移动到位,创建一个新文件(与以前同名)以保存新的日志条目,指示程序生成消息以使用新文件,然后(可选)压缩旧文件。您可以配置要保留的旋转日志数。这是一个潜在的教程: http://www.debian-administration.org/articles/117
这并不是您想要的界面(保留一定数量的线条),但程序可能比您自己烹饪的更强大;例如,这里的答案不涉及原子地移动文件并通知日志程序使用新文件,因此存在一些日志消息丢失的风险。