Запись файлов журнала фильтра в зависимости от диапазона дат

У моего сервера необычно высокий уровень использования ЦП, и я вижу, что Apache использует слишком много памяти. У меня такое чувство, что я являюсь DOS'd одним IP - возможно, вы можете помочь мне найти его?

Я использовал следующую строку, чтобы найти 10 самых "активных" IP-адресов:

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

Топ-5 IP-адресов имеют примерно в 200 раз больше запросов к серверу, как "средний" пользователь. Однако я не могу узнать, являются ли эти 5 очень частыми посетителями или они атакуют серверы.

Есть ли способ указать указанный выше поиск на временной интервал, например. последние два часа или между 10-12 сегодня?

Ура!

ОБНОВЛЕНО 23 октября 2011 г. - Необходимые команды:

Получить записи за последние X часов [Здесь два часа]

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

Получить наиболее активные IP-адреса за последние X часов [здесь два часа]

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

да, есть несколько способов сделать это. Вот как я пошла бы по этому поводу. Для начала нет необходимости передавать вывод 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, может оказаться полезным. Печать даты в понедельник текущей недели (в bash)

Ответ 2

Если кто-то встречается с awk: invalid -v option, здесь script, чтобы получить наиболее активные 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

Ответ 3

Поскольку это общий perl задача

И поскольку это не совсем то же самое, что извлечь последние 10 минут из файла журнала, где он содержит кучу времени до конца файла журнала.

И поскольку я нуждался в них, я (быстро) написал это:

#!/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. Не упускайте знак равенства = и пробелы!

Nota:. Это два разных типа регулярных выражений для двух разных стандартных журналов. Если вам нужен разный синтаксис формата даты и времени, отправьте собственное регулярное выражение или опубликуйте образец отформатированной даты из вашего файла журнала

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