从包含大于某个日期时间的日志文件中解析行

时间:2016-10-04 13:44:25

标签: parsing grep nagios

我的日志文件大小为几百MB,包含这样的行,包含开头的日期时间信息:

[Tue Oct  4 11:55:19 2016] [hphp] [25376:7f5d57bff700:279809:000001] [] \nFatal error: syntax error, unexpected T_ENCAPSED_AND_WHITESPACE, expecting ')' in /var/cake_1.2.0.6311-beta/app/webroot/openx/www/delivery/postGetAd.php(12479)(62110d90541a84df30dd077ee953e47c) : eval()'d code on line 1

我有一个插件(nagios check_logwarn)只打印出那些包含一些错误字符串的行。以下是运行它的命令:

/usr/local/nagios/libexec/check_logwarn -d /tmp/logwarn -p /mnt/log/hiphop/error_20161003.log "^.*Fatal error*" 

我想根据日期时间进一步过滤,即所有后面的行,比如说11:55:10。

我不确定是否要使用正则表达式。以下是我到目前为止:

/usr/local/nagios/libexec/check_logwarn -d /tmp/logwarn -p /mnt/log/hiphop/error_20161003.log "^.*Fatal error*" | grep "15\:19\:1*"

但这只会过滤那些时间在第15小时第19分钟的日志。

更新

我现在能够比较日期时间的时间部分。

/usr/local/nagios/libexec/check_logwarn -d /tmp/logwarn -p /mnt/log/hiphop/error_20161004.log "^.*Fatal error*" | awk '$4 > "14:22:11"'

如何比较日期部分?

更新2 - 打开赏金

我必须开一个赏金,因为我对shell没有太多的专业知识,我很快就需要一个解决方案。

我被困在比较日期的部分。使用解决方案https://stackoverflow.com/a/39856560/351903,我面临this problem。如果这是固定的,我会很高兴。

我也对此进行了一些改进(我不介意输出是否有一些混乱的日志顺序) -

/usr/local/nagios/libexec/check_logwarn -d /tmp/logwarn -p /mnt/log/hiphop/error_20161004.log "^.*Fatal error*" | awk '$4 > "14:22:11"'

我查找了时间戳比较的日期时间,但找不到合适的东西。

我无法继续this question中给出的内容。我无法使用这个 -

看到时间戳值
echo date -d '06/12/2012 07:21:22' +"%s"

不确定我错过了什么。

2 个答案:

答案 0 :(得分:0)

这使用引用时间戳并将日志文件中的时间戳与之比较;如果日志文件的时间戳更新,则会打印该行:

awk -v refdate="$(date +'%s' -d 'Mon Oct 3 10:00:00 2016')" -F "[][]" '
    {
        cmd = "date +\047%s\047 -d \"" $2 "\""
        if ((cmd | getline val) > 0) {
            if (val > refdate)
                print
        }
        close(cmd)
    }
' infile

以下是它的工作原理:

  • -v refdate="$(date +'%s' -d 'Mon Oct 3 10:00:00 2016')"将给定的日期(我们的参考日期)转换为自纪元以来的秒数。
  • -F "[][]"将字段分隔符设置为方括号,因此我们想要的时间戳只是$2
  • "date +\047%s\047 -d \"" $2 "\""是我们要执行的shell命令;它变为date +'%s' -d "$2",即它将日志文件时间戳转换为自纪元以来的秒数。 \047是单引号。
  • command | getline val评估command并将结果分配给val,因此val现在保存自纪元以来的日志文件中的时间戳。
    • 我们使用getline检查(cmd | getline val) > 0的成功与否。
  • 如果getline成功,if (val > refdate) print会将日志文件时间戳与参考日期进行比较,如果日志文件时间戳更新,则会打印该行。
  • close(cmd)关闭了管道。

<强>参考

答案 1 :(得分:0)

您需要可比日期表示

正则表达式可以用于提取数据,但这是将日期相互比较的可怕方法。实际上,您需要将时间戳转换为可比较的时间戳,例如Epoch time或DateTime对象。如果要查找包含时间戳大于某个其他时间戳的所有行,则需要解析每行中的时间戳以进行比较。

Ruby示例

#!/usr/bin/env ruby

require 'date'

# Convert your given timestamp to something comparable.
timestamp = DateTime.parse ARGV.first

# Loop over each line of your logfile.
File.open(ARGV.last).each_line do |line|
  # Use a rather naive regex to extract the timestamp from each line.
  next if line !~ /^\[.*?\]/

  # Print lines that contain a later timestamp than your target.
  puts line if DateTime.parse($&) > timestamp
end

该脚本有两个位置参数:

  1. 类似于RFC 2822的时间戳,有或没有时区偏移。
  2. 要解析的文件。
  3. 然后脚本比较每一行的时间戳,并仅打印早于作为参数传递的时间戳的行。您可以修改从>>=的比较,如果您的意思是&#34;晚于或等于&#34;您给定的时间戳,可能更直观。

    例如:

    ruby /tmp/parse_log_dates.rb "Tue Oct  4 11:55:18 2016" /path/to/logfile
    

    在您提供的非常有限的语料库中工作得很好。您的实际结果可能会有所不同,尤其是如果您的日志文件实际上不包含每行的时间戳。