根据date范围筛选日志文件条目

我的服务器CPU使用率exception高,而且我可以看到Apache使用太多的内存。 我有一种感觉,我被一个单一的知识产权所困扰 – 也许你能帮我find他吗?

我使用了下面这行,find了10个最“活跃”的IP:

cat access.log | awk '{print $1}' |sort |uniq -c |sort -n |tail 

前5个IP的服务器请求量是“平均”用户的200倍。 但是,我不能确定这5位访客是否非常频繁,或者他们正在攻击服务器。

有没有办法,指定上述search到一个时间间隔,例如。 最近两个小时或10-12今天?

干杯!

更新2011年10月23日 – 我需要的命令:

获取最近X小时内的条目[这里两个小时]

 awk -vDate=`date -d'now-2 hours' +[%d/%b/%Y:%H:%M:%S` ' { if ($4 > Date) print Date FS $4}' access.log 

在最近的X小时内获得最活跃的IP [在这里两个小时]

 awk -vDate=`date -d'now-2 hours' +[%d/%b/%Y:%H:%M:%S` ' { if ($4 > Date) print $1}' access.log | sort |uniq -c |sort -n | tail 

获取相对时间范围内的条目

 awk -vDate=`date -d'now-4 hours' +[%d/%b/%Y:%H:%M:%S` -vDate2=`date -d'now-2 hours' +[%d/%b/%Y:%H:%M:%S` ' { if ($4 > Date && $4 < Date2) print Date FS Date2 FS $4}' access.log 

获取绝对时间范围内的条目

 awk -vDate=`date -d '13:20' +[%d/%b/%Y:%H:%M:%S` -vDate2=`date -d'13:30' +[%d/%b/%Y:%H:%M:%S` ' { if ($4 > Date && $4 < Date2) print $0}' access.log 

在绝对时间范围内获取最活跃的IP

 awk -vDate=`date -d '13:20' +[%d/%b/%Y:%H:%M:%S` -vDate2=`date -d'13:30' +[%d/%b/%Y:%H:%M:%S` ' { if ($4 > Date && $4 < Date2) print $1}' access.log | sort |uniq -c |sort -n | tail 

是的,有多种方法可以做到这一点。 这是我如何去做这件事。 对于初学者来说,不需要pipe道猫的输出,只需用awk打开日志文件即可。

 awk -vDate=`date -d'now-2 hours' +[%d/%b/%Y:%H:%M:%S` '$4 > Date {print Date, $0}' access_log 

假设你的日志看起来像我的(他们是可configuration的)date是存储在字段4,并被括起来。 我上面正在做的是在最近2个小时内find一切。 Note the -d'now-2 hours'或翻译字面上现在减2小时,这对我来说是这样的: [10/Oct/2011:08:55:23

所以我正在做的是存储两个小时前的格式化值,并与四个字段进行比较。 条件expression式应该是直截了当的。然后打印date,然后是输出字段分隔符(OFS – 或本例中的空格),然后是整行$ 0。 你可以使用你以前的expression式,并打印$ 1(的IP地址)

 awk -vDate=`date -d'now-2 hours' +[%d/%b/%Y:%H:%M:%S` '$4 > Date {print $1}' | sort |uniq -c |sort -n | tail 

如果您想使用范围指定两个datevariables并适当地构build您的expression式。

所以如果你想在2-4小时之前find一些东西,你的表情可能看起来像这样

 awk -vDate=`date -d'now-4 hours' +[%d/%b/%Y:%H:%M:%S` -vDate2=`date -d'now-2 hours' +[%d/%b/%Y:%H:%M:%S` '$4 > Date && $4 < Date2 {print Date, Date2, $4} access_log' 

这里是一个问题,我回答了有关在bash中的date,你可能会发现有帮助。 本周星期一的打印date(以bash为单位)

因为这是一个普通的 perl任务

而且,因为这与从logfile中提取最后10分钟的内容不完全相同,因为它是关于一段时间直到logfile结束的时间。

而且因为我需要他们,所以我(很快)写下了这个:

 #!/usr/bin/perl -ws # This script parse logfiles for a specific period of time sub usage { printf "Usage: %s -s=<start time> [-e=<end time>] <logfile>\n"; die $_[0] if $_[0]; exit 0; } use Date::Parse; usage "No start time submited" unless $s; my $startim=str2time($s) or die; my $endtim=str2time($e) if $e; $endtim=time() unless $e; usage "Logfile not submited" unless $ARGV[0]; open my $in, "<" . $ARGV[0] or usage "Can't open '$ARGV[0]' for reading"; $_=<$in>; exit unless $_; # empty file # Determining regular expression, depending on log format my $logre=qr{^(\S{3}\s+\d{1,2}\s+(\d{2}:){2}\d+)}; $logre=qr{^[^\[]*\[(\d+/\S+/(\d+:){3}\d+\s\+\d+)\]} unless /$logre/; while (<$in>) { /$logre/ && do { my $ltim=str2time($1); print if $endtim >= $ltim && $ltim >= $startim; }; }; 

这可以用来:

 ./timelapsinlog.pl -s=09:18 -e=09:24 /path/to/logfile 

用于在09h18和09h24之间打印日志。

 ./timelapsinlog.pl -s='2017/01/23 09:18:12' /path/to/logfile 

january 23th, 9h18'12"january 23th, 9h18'12"印刷。

为了减lessperl代码,我使用-s切换来允许从命令行自动分配variables: -s=09:18 09:18将填充variables$s将包含09:18 。 小心不要错过等号= ,也不要有空格!

注意:这为两种不同的日志标准提供了两种不同的正则expression式 。 如果您需要不同的date/时间格式parsing,请发布您自己的正则expression式或从日志文件中发布格式化date的示例

 ^(\S{3}\s+\d{1,2}\s+(\d{2}:){2}\d+) # ^Jan 1 01:23:45 ^[^\[]*\[(\d+/\S+/(\d+:){3}\d+\s\+\d+)\] # ^... [01/Jan/2017:01:23:45 +0000] 

如果有人遇到awk: invalid -v option ,下面是一个脚本,可以在预定义的时间范围内获得最活跃的IP:

 cat <FILE_NAME> | awk '$4 >= "[04/Jul/2017:07:00:00" && $4 < "[04/Jul/2017:08:00:00"' | awk '{print $1}' | sort -n | uniq -c | sort -nr | head -20