邮件服务器日志过滤

时间:2011-03-27 16:38:48

标签: perl postfix-mta

我有多GB邮件服务器日志文件和~350k邮件ID列表。 我想从长列表中删除带有ID的大日志文件行......我希望它比现在更快... 目前我在perl中做到了:

#!/usr/bin/perl

use warnings;

#opening file with the list - over 350k unique ID
open ID, maillog_id;
@lista_id = <ID>;
close ID;
chomp @lista_id;

open LOG, maillog;
# while - foreach would cause out of memory
while ( <LOG> ) {
        $wiersz = $_;
        my @wiersz_split = split ( ' ' , $wiersz );
        #
        foreach ( @lista_id ) {
          $id   = $_;
          # ID in maillog is 6th column
          if ( $wiersz_split[5] eq $id)  {
            # print whole row when matched - can be STDOUT or file or anything
            print "@wiersz_split\n";
          }
        }
}
close LOG;

它有效但速度很慢......日志中的每一行都与ID列表进行比较。 我应该使用数据库并执行一种连接吗?或者比较子串?

有许多用于日志分析的工具 - 例如pflogsumm ...但它只是总结。例如。我可以用

grep -c "status=sent" maillog

它会很快但没用,我会在过滤我的日志文件后使用它...同样适用于pflogsumm等 - 只是增加变量。

有什么建议吗?

-------------------- UPDATE -------------------

谢谢Dallaylaen, 我成功了(而不是@lista_id上的内部foreach:

if ( exists $lista_id_hash{$wiersz_split[5]} ) { print "$wiersz"; }

其中%lista_id_hash是一个哈希表,其中键是从我的ID列表中获取的项目。它的工作速度非常快。 使用&gt; 350k ID处理4,6 GB日志文件只需不到1分钟即可过滤有趣的日志。

1 个答案:

答案 0 :(得分:2)

使用哈希。

my %known;
$known{$_} = 1 for @lista_id;
# ...
while (<>) {
    # ... determine id
    if ($known{$id}) {
         # process line
    };
};

P.S。如果您的日志很大,那么根据例如你的日志分割它可能会更好。将$ id的最后两个字母分成256(或36 ** 2?)个较小的文件。有点像穷人的MapReduce。一次存储在内存中的ID数量也将减少(即,当您处理maillog.split.cf时,您应该只保留以散列中的“cf”结尾的ID。)