2011-10-09 122 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