2011-10-09 166 views
27

我的服务器的CPU使用率异常高,而且我可以看到Apache使用的存储方式太多了。 我有一种感觉,我被一个单一的IP DOS - 也许你可以帮我找到他?根据日期范围筛选日志文件条目

我用下面的行,寻找10个最“活跃”的IP:

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

前5位的IP约200倍的对服务器的请求,作为“平均”用户。但是,我无法确定这5位访问者是否非常频繁,或者他们正在攻击服务器。

是否有办法,指定上述搜索到一个时间间隔,例如。最近两个小时或今天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 
+1

我很懒;我将日志复制到Excel中并创建一个数据透视表... – Ben

+0

@Ben“现在你有两个问题。” – tripleee

回答

29

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

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

假设您的日志看起来像我(他们配置)于日期存储在字段4,并加括号。我在上面做的是在最近2个小时内找到所有东西。 Note the -d'now-2 hours'或现在翻译字面现在减2小时这对我来说看起来像这样:[10/Oct/2011:08:55:23

所以我正在做的是存储两个小时前的格式化值和比较字段四。条件表达式应该是直截了当的。然后我打印日期,然后是输出字段分隔符(OFS - 或本例中的空格),然后是整行$ 0。你可以使用以前的表达,只是打印$ 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 

如果你想使用范围指定两个日期变量,并适当构建您的表达。

所以,如果你想确实发现前你表达可能2-4hrs之间的事情看起来是这样的

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日期可能会找到有用的一个问题。 Print date for the monday of the current week (in bash)

+0

谢谢你!很好的例子,很好的解释。我已经详细阐述了您的代码以满足我的特定需求,并将其添加到原始问题中供将来为我和其他需要的人员参考。 – sqren

+0

我很高兴它可以提供帮助。 – matchew

+0

最后一件事。我如何通过多个日志文件进行搜索? 我正在尝试使用find和xargs,但仍然没有运气: find -name'access.log'| awk -vDate ='date -d '13:20'+ [%d /%b /%Y:%H:%M:%S' -vDate2 ='date -d'13:40'+ [%d/%b /%Y:%H:%M:%S''{if($ 4> Date && $ 4 sqren

1

由于这是一个常见的任务

而且因为这是不完全不是同一extract last 10 minutes from logfile它的日志文件高达的结束了一堆的时间。 09h18和09h24之间

./timelapsinlog.pl -s=09:18 -e=09:24 /path/to/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='2017/01/23 09:18:12' /path/to/logfile 

january 23th, 9h18'12"打印高达现在

为了减少Perl代码,我用-s开关允许从命令行变量自动assignement:-s=09:18将填充变量$s至极将包含09:18。注意不要错过等号=而且没有空格!

注意:对于两种不同的日志标准,这两种不同的正则表达式。如果你需要不同的日期/时间格式解析,无论是发布自己的正则表达式或从你的日志文件

^(\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] 
+0

非常好的回复,我将它添加到一个循环中,我可以轻松地调查服务器上发生了什么。 – user322049

1

发布格式的日期的样本。如果有人用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