Запись файлов журнала фильтра в зависимости от диапазона дат
У моего сервера необычно высокий уровень использования ЦП, и я вижу, что 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]