解析输出量很大的日志文件

解析输出量很大的日志文件

我想监控我的 vsftpd 日志并从日志中提取信息来处理已上传的文件。到目前为止,一切都很顺利,运行良好:

tail -n0 -F /var/log/vsftpd.log | while read line; do
    if echo "$line" | grep -q 'OK UPLOAD:'; then
        #do a bunch of processing stuff - this takes some time
    fi
done

我开始进行一些规模测试,并一次上传了 500 个文件。由于某种原因,当您上传太多内容时,日志行会丢失或被截断。例如,典型的一行如下所示:

Sun Apr 7 09:08:51 2013 [pid 25409] [cam02430] OK UPLOAD: Client "206.132.183.201", "/20130407/09/20130407_090842D.avi", 531792 bytes, 426.14Kbyte/sec

但有时该行看起来像这样(如果没有完全缺失):

:08:51 2013 [pid 25409] [cam02430] OK UPLOAD: Client "206.132.183.201", "/20130407/09/20130407_090842D.avi", 531792 bytes, 426.14Kbyte/sec

它截断了日志的前几个字符。它不会对每一行都这样做,但会截断大部分行。而且很多行都丢失了。我想我遇到了处理无法及时完成的​​竞争条件。我该如何解决这个问题?

编辑 我想我有 3 个选择:

  1. 不要使用 tail,而要尝试使用 cron 作业/grep 等组合来检查日志中是否有新条目。我想这可能很棘手。我如何知道该日志中有什么新内容?

  2. 使用 monit 或同等工具监控文件更改。我不认为这是一个选项。文件被存储在带有时间戳的文件名的随机目录中。

  3. logstash 或类似程序。我认为这些程序不符合我的需求。但也许有人知道其他情况。

现在我正专注于 #1,没有好的线索。因此,任何关于这方面的想法都将不胜感激。

答案1

您可以启动以防止分叉“grep”进程每一个在日志中的行中,通过像这样重写代码:

tail -n0 -F /var/log/vsftpd.log | grep 'OK UPLOAD:' | while read line ; do
        #do a bunch of processing stuff - this takes some time
done

但我同意其他发帖者的观点,shell 并不适合处理繁重的文本/字符串。你应该考虑使用其他脚本引擎(至少是 awk,或者更好的是 perl 或 python)

答案2

如果您愿意放宽对 shell 脚本的限制,那么我在使用文件打开 '<' 选项的 Perl 方面拥有丰富的经验。

例如https://stackoverflow.com/questions/1425223/how-do-i-read-a-file-which-is-constantly-updating

答案3

正如@epoon建议,Perl 可能是一个不错的选择:

#!/usr/bin/env perl

open(FH,'<',$ARGV[0]) || die("Could not open file $ARGV[0]\n");
for (;;) {
    while (<FH>) {
    if (/OK UPLOAD/) { ## this is where you do your processing. As an example, 
                       ## I am collecting the file's info
        /^(.+?)\s*\[pid\s*(\d+).+?\"([\d\.]+).+?\"(.+?)\".+?(\d+).+?\s([^\s]+)/;
        my ($date,$pid,$client,$filename,$size,$rate) = ($1,$2,$3,$4,$5,$6);
        print "On $date, process $pid uploaded file \"$filename\" of $size bytes from $client at $rate\n"

    }
    }
    # eof reached on FH, but wait a second and maybe there will be more output
    sleep 1;
    seek FH, 0, 1;      # this clears the eof flag on FH
}

运行此脚本/var/log/vsftpd.log应该给出类似的输出

On Sat Apr 20 16:30:05 CEST 2013, process 25409 uploaded file "/20130407/09/20130407_090842D.avi" of 531792 bytes from 206.132.183.201 at 426.14Kbyte/sec

如果您具体说明想要用日志信息做什么,我会很乐意更新此信息。

答案4

您是否尝试过使用该--line-buffered选项grep

tail -f /var/log/vsftpd.log | grep --line-buffered 'OK UPLOAD:' | while read line ; do
        #do a bunch of processing stuff - this takes some time
done

相关内容