我的日志文件大小为几百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"
不确定我错过了什么。
答案 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)
关闭了管道。<强>参考强>
date -d
非常灵活,能够理解日期字符串中的大量格式,请参阅date
manual。getline
位于gawk user manual和freeshell.org上(小贴士Ed Morton,他还指出如何在他的有用评论中正确使用getline
)< / LI>
答案 1 :(得分:0)
正则表达式可以用于提取数据,但这是将日期相互比较的可怕方法。实际上,您需要将时间戳转换为可比较的时间戳,例如Epoch time或DateTime对象。如果要查找包含时间戳大于某个其他时间戳的所有行,则需要解析每行中的时间戳以进行比较。
#!/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
该脚本有两个位置参数:
然后脚本比较每一行的时间戳,并仅打印早于作为参数传递的时间戳的行。您可以修改从>
到>=
的比较,如果您的意思是&#34;晚于或等于&#34;您给定的时间戳,可能更直观。
例如:
ruby /tmp/parse_log_dates.rb "Tue Oct 4 11:55:18 2016" /path/to/logfile
在您提供的非常有限的语料库中工作得很好。您的实际结果可能会有所不同,尤其是如果您的日志文件实际上不包含每行的时间戳。