我有agent.log文件。此文件以常规间隔更新。
条目如下2014-01-07 03:43:35,223 INFO ...some data
我想提取最后3分钟的数据,有没有办法让我使用bash脚本获取这些数据?
答案 0 :(得分:8)
尝试以下解决方案:
awk \
-v start="$(date +"%F %R" --date=@$(expr `date +%s` - 180))" \
-v end="$(date "+%F %R")" \
'$0 ~ start, $0 ~ end' \
agent.log
在start
变量中,时间戳在当前时间之前3分钟(180秒)。
在end
中有当前时间。
$0 ~ start, $0 ~ end
选择start
和end
答案 1 :(得分:4)
date +"%F %R"
为您提供当前时间。
grep '^'"$(date +"%F %R")" agent.log
将从文件中选择最后一分钟
现在前两分钟它更棘手......我已经开发了一些脚本可以完成相对或绝对的时间操作,它可能比摆弄date
...
2分钟前,格式正确:date --date="@$(($(date +"%s") - 2*60))" +"%F %R"
合并所有3:
NOW=$(date +"%F %R")
M1=$(date --date="@$(($(date +"%s") - 1*60))" +"%F %R")
M2=$(date --date="@$(($(date +"%s") - 2*60))" +"%F %R")
grep '^'"$NOW\|$M1\|$M2" agent.log
答案 2 :(得分:2)
我的回答考虑了以下几点:
整个脚本应该可以扩展为反向或指定的从 - 到间隔
#!/bin/bash
# this script expects descending dates in a log file (reverse as real life examples)!!!
FILE=$1
INTV=180 # sec
while read LINE
do
if [ -z $LAST_LOG_LINE ]
then
# interval stat line
LAST_LOG_LINE=$(date --date="$( echo "$LINE" | sed -e 's/INFO.*//')" +%s)
# mod
#continue
fi
ACT_LOG_LINE=$(date --date="$( echo "$LINE" | sed -e 's/INFO.*//')" +%s)
# print line if not greater than $INTV (180s)
# else break the reading and exit
if [ $(($LAST_LOG_LINE-$ACT_LOG_LINE)) -gt $INTV ]
then
break
fi
# actual print
echo "$LINE"
done < $FILE
测试:
2014-01-07 03:43:35,223 INFO ...some data
2014-01-07 03:42:35,223 INFO ...some data
2014-01-07 03:41:35,223 INFO ...some data
2014-01-07 03:40:35,223 INFO ...some data
2014-01-07 02:43:35,223 INFO ...some data
2014-01-07 01:43:35,223 INFO ...some data
2014-01-06 03:43:35,223 INFO ...some data
$ /tmp/stack.sh /tmp/log
2014-01-07 03:42:35,223 INFO ...some data
2014-01-07 03:41:35,223 INFO ...some data
2014-01-07 03:40:35,223 INFO ...some data
$
答案 3 :(得分:0)
我认为在这种情况下使用Python可能会好一些。即使此脚本在3分钟前没有找到日期,它仍会在调用脚本和3分钟前之间获得任何日志条目。这比以前提供的一些解决方案更简洁,更健壮。
#!/usr/bin/env python
from datetime import datetime, timedelta
with open('agent.log') as f:
for line in f:
logdate = datetime.strptime(line.split(',')[0], '%Y-%m-%d %H:%M:%S')
if logdate >= datetime.now() - timedelta(minutes=3):
print(line)
答案 4 :(得分:0)
您可以将天,小时,分钟或秒作为参数传递,它将搜索表达式和指定的文件(或目录,在这种情况下,它将附加&#39; / *&#39;名):
在你的情况下,只需调用脚本:$ 0 -m 3&#34; expression&#34; LOG_FILE
注意:如果您知道&#39; ruby&#39;的位置。改变shebang(脚本的第一行), 出于安全考虑。
#! /usr/bin/env ruby
require 'date'
require 'pathname'
if ARGV.length != 4
$stderr.print "usage: #{$0} -d|-h|-m|-s time expression log_file\n"
exit 1
end
begin
total_amount = Integer ARGV[1]
rescue ArgumentError
$stderr.print "error: parameter 'time' must be an Integer\n"
$stderr.print "usage: #{$0} -d|-h|-m|-s time expression log_file\n"
end
if ARGV[0] == "-m"
gap = Rational(60, 86400)
time_str = "%Y-%m-%d %H:%M"
elsif ARGV[0] == "-s"
gap = Rational(1, 86400)
time_str = "%Y-%m-%d %H:%M:%S"
elsif ARGV[0] == "-h"
gap = Rational(3600, 86400)
time_str = "%Y-%m-%d %H"
elsif ARGV[0] == "-d"
time_str = "%Y-%m-%d"
gap = 1
else
$stderr.print "usage: #{$0} -d|-h|-m|-s time expression log_file\n"
exit 1
end
pn = Pathname.new(ARGV[3])
if pn.exist?
log = (pn.directory?) ? ARGV[3] + "/*" : ARGV[3]
else
$stderr.print "error: file '" << ARGV[3] << "' does not exist\n"
$stderr.print "usage: #{$0} -d|-h|-m|-s time expression log_file\n"
end
search_str = ARGV[2]
now = DateTime.now
total_amount.times do
now -= gap
system "cat " << log << " | grep '" << now.strftime(time_str) << ".*" << search_str << "'"
end