2011-10-09 15 views
27

Mój serwer ma niezwykle wysokie użycie procesora i widzę, że Apache używa zbyt dużo pamięci. Mam przeczucie, że otrzymałem DOS za pomocą jednego adresu IP - może pomożesz mi go znaleźć?Filtruj wpisy w pliku dziennika na podstawie zakresu dat

Użyłem następujące polecenie, aby znaleźć 10 najbardziej „aktywnych” IP:

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

5 najlepszych IP mają około 200 razy więcej żądań do serwera, jako „przeciętnego” użytkownika . Jednak nie mogę się dowiedzieć, czy te 5 to bardzo często odwiedzający, czy atakują serwery.

Czy istnieje sposób, aby określić powyższe wyszukiwanie do przedziału czasu, np. ostatnie dwie godziny LUB od 10 do 12 dzisiaj?

Pozdrawiam!

Updated 23 Paź 2011 - Polecenia Potrzebowałem:

Get wpisy w ciągu kilku godzin w ostatnim X [tu dwie godziny]

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

Get najaktywniejsze IP w godzinach ostatni X [tu dwa godziny]

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 

Get wpisy ciągu względnej przedziale czasu

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 

Get wpisy w absolutnej przedziale czasu

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 

uzyskać większość bezwzględną aktywnych IP w przedziale czasu

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

Jestem leniwy; Chciałbym skopiować dziennik do programu Excel i utworzyć tabelę przestawną ... – Ben

+0

@Ben "Teraz masz dwa problemy." – tripleee

Odpowiedz

29

tak, istnieje wiele sposobów, aby to zrobić. Oto, jak to zrobię. Na początek, nie trzeba potokować wyjścia kota, wystarczy otworzyć plik dziennika z awk.

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

zakładając swoją log wygląda kopalni (są konfigurowalne) niż data jest przechowywana w polu 4. i jest w nawiasie. To, co robię powyżej, to znajdowanie wszystkiego w ciągu ostatnich 2 godzin. Note the -d'now-2 hours' lub przetłumaczone dosłownie teraz minus 2 godziny, które dla mnie wygląda mniej więcej tak: [10/Oct/2011:08:55:23

Więc to, co robię, to przechowywanie sformatowanej wartości dwie godziny temu i porównanie z polem czwartym. Wyrażenie warunkowe powinno być proste. Następnie drukuję datę, a następnie separator pola wyjściowego (OFS - lub spacja w tym przypadku), a następnie cały wiersz 0 USD. Można użyć poprzedniego wyrażenia i po prostu wydrukować $ 1 (adresy IP)

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

Jeśli chciał wykorzystać szereg określić dwa date zmienne i skonstruować swój wyraz w odpowiedni sposób.

więc jeśli nie chciał znaleźć coś pomiędzy 2-4hrs temu Mocą ekspresji wyglądać tak

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' 

o to pytanie odpowiedziałem dotyczące dat w bash można znaleźć pomocne. Print date for the monday of the current week (in bash)

+0

Dzięki! Świetne przykłady z dobrymi objaśnieniami. Opracowałem Twój kod dla moich konkretnych potrzeb i dodałem go do pierwotnego pytania, aby móc w przyszłości znaleźć dla siebie i innych potrzebujących. – sqren

+0

Cieszę się, że to może być pomocne. – matchew

+0

Ostatnia rzecz. Jak przeszukiwać wiele plików dziennika? Próbuję z find i xargs, ale nadal nie ma szczęścia: 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 $> Data i 4 $ sqren

1

Ponieważ jest to wspólny zadanie

A ponieważ to nie jest dokładnie to samo niż extract last 10 minutes from logfile gdzie chodzi o grono czasie zapisu do końca pliku dziennika.

A ponieważ mam ich potrzebował, I (szybko) napisał:

#!/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; 
    }; 
}; 

To może być używany jak:

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

do drukowania dzienników pomiędzy 09h18 i 09h24.

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

do drukowania z january 23th, 9h18'12" września teraz.

W celu zmniejszenia kod perla, Użyłem -s przełącznik, aby umożliwić automatyczne ASSIGNMENT zmiennych z poleceń: -s=09:18 propaguje zmienna $s wich będzie zawierać 09:18. Uważaj, aby nie przegapić znaku równości = i bez spacji!

Nota: Ten przytrzymać dwa diffent rodzaju regex dla dwóch różnych standardów dziennika. Jeśli potrzebujesz inny format daty/czas parsowania, albo zakładać własną regex lub umieścić próbkę sformatowanej daty z pliku dziennika

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

Bardzo ładna odpowiedź, dodałem to do pętli i mogę łatwo sprawdzić, co się stało na serwerze. – user322049

1

jeśli ktoś napotka z awk: invalid -v option, oto skrypt, aby uzyskać najbardziej aktywnych adresów IP w krótkim czasie predefiniowany zakres czasowy:

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 
Powiązane problemy