根据日期范围过滤日志文件条目

时间:2011-10-09 19:47:45

标签: linux apache ubuntu awk

我的服务器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

3 个答案:

答案 0 :(得分:38)

是的,有多种方法可以做到这一点。以下是我将如何做到这一点。对于初学者,无需管道cat的输出,只需使用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-4小时之前找到一些东西,你的表达可能看起来像这样

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)

答案 1 :(得分:2)

如果有人遇到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

答案 2 :(得分:1)

因为这是常见的 任务

因为这与extract last 10 minutes from 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" 打印到现在

为了减少perl代码,我使用了-s切换来允许从命令行自动分配变量:-s=09:18将填充将包含$s的变量09:18 {1}}。注意不要错过等号=而不能错过任何空格!

Nota:这为两种不同的日志标准保留了两种不同的 regex 。如果您需要不同的日期/时间格式解析,请发布您自己的正则表达式或从您的日志文件发布格式化日期的样本

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