grep конкретная запись журнала больше определенного времени

Использование данных вашего примера:

$ join <(sort file1) <(sort file2)
ARS-BFGL-BAC-10975 0.9303 688423261 1 01/04/2015 0.9983763305 10 21225382
ARS-BFGL-BAC-10975 0.9303 688423263 1 01/04/2015 0.9983763305 10 21225382
ARS-BFGL-BAC-11025 0.9092 688423261 1 01/04/2015 0.9983763305 10 84516867
ARS-BFGL-BAC-11025 0.9092 688423263 1 01/04/2015 0.9983763305 10 84516867
ARS-BFGL-BAC-11193 0.9544 688423261 1 01/04/2015 0.9983763305 1 29303546
ARS-BFGL-BAC-11193 0.9544 688423263 1 01/04/2015 0.9983763305 1 29303546

Похоже, это делает то, что вы от него хотите, за исключением порядка строк в выводе (, который отсортирован здесь, и я не знаю, важно ли это для вас. или нет ).

Поле соединения по умолчанию является первым полем, поэтому -j 1не требуется (это расширение GNU join).

Выход по умолчаниюjoin:«Каждый строка вывода состоит из поля соединения, остальные поля из файла1 а затем оставшиеся поля из файла2" (из руководства OpenBSD ). Это означает, что спецификация поля вывода, которую вы использовали, также не нужна, поскольку она соответствует поведению по умолчанию.

Для sort-k1также эквивалентно значению по умолчанию.

Я не знаю, что вызвало сообщение об ошибке, кроме случайного использования sort -c.

2
08.12.2019, 15:19
4 ответа

С помощью tsиз moreutilsвы можете легко преобразовать эти метки времени в более удобный формат:

ts -r %FT%T%z < file.log |
  awk '$0 > "[2019-12-04T02:50" && tolower($0) ~ /failed login/'

Что на вашем вводе (и в часовом поясе America/Los_Angeles)дает:

[2019-12-04T03:05:18-0800] access       WARNING  10.126.49.92 -anon- - "POST /hue/accounts/login HTTP/1.1"-- Failed login for user: testuser

tsс -rанализирует эту метку времени и преобразует ее в указанный формат%FT%T%zstrftime(в вашем часовом поясе ).

Поскольку этот формат YYYY-MM-DDTHH:MM:SSсортирует одинаково лексически и в хронологическом порядке¹, тогда просто нужно выполнить сравнение строк в awk, чтобы найти эти записи позже указанной даты. awkтакже может выполнять работу grep -i. Здесь используется стандартный подход tolower()для совпадения без учета регистра. С GNU awkвы также можете:

gawk -v IGNORECASE=1 '$0 > "[2019-12-04T02:50" && /failed login/'

Если у вас нет moreutils, вы можете выполнить синтаксический анализ с помощью perl, Time::Piece, например,(ts— это perl-скрипт, который использует Date::Parse, но в отличие от Time::Piece, это не так. один из основных модулей perl, поэтому может не устанавливаться в вашей системе):

CUT=2019-12-04T02:50:00-0800 perl -MTime::Piece -F'[][]' -ale '
  BEGIN{$cut = Time::Piece->strptime($ENV{CUT}, "%FT%T%z")}
  print if /failed login/i &&
           Time::Piece->strptime($F[1], "%d/%b/%Y %T %z") >= $cut' < file.log

¹ если мы проигнорируем метки во время смены зимних/летних часов в часовых поясах, которые переходят на летнее время

4
27.01.2020, 21:58

Я оставляю это на случай, если кому-то это покажется полезным, но вместо этого просто используйте этот ответ . Это намного проще и эффективнее.


Вот перловый способ:

$ perl -lne 'if(/^\[([^]]+)/){$d=$1; chomp($dateThreshold=`date -d "04 Dec 2019" +%s`); $d=~s|/| |g; chomp($d=`date -d "$d" +%s`); print if $d >= $dateThreshold;} ' test.log 
[04/Dec/2019 02:05:13 -0800] access       WARNING  10.126.49.92 -anon- - "POST /hue/accounts/login HTTP/1.1"-- Failed login for user: testuser
[04/Dec/2019 02:05:15 -0800] access       WARNING  10.126.49.92 -anon- - "POST /hue/accounts/login HTTP/1.1"-- Failed login for user: testuser
[04/Dec/2019 02:04:59 -0800] access       INFO     10.126.49.92 ahmed.rao - "POST /notebook/api/check_status HTTP/1.1" returned in 759ms
[04/Dec/2019 02:05:00 -0800] base         INFO     Selected cluster 0e83a448-26c9-459b-a0f2-3478ecb119af {u'interface': u'impala', u'namespace': u'0e83a448-26c9-459b-a0f2-3478ecb119af', u'type': u'direct', u'id': u'0e83a448-26c9-459b-a0f2-3478ecb119af', u'name': u'0e83a448-26c9-459b-a0f2-3478ecb119af'} interface hiveserver2
[04/Dec/2019 03:05:00 -0800] access       INFO     10.126.49.92 ahmed.rao - "POST /notebook/api/close_statement HTTP/1.1" returned in 1345ms
[04/Dec/2019 03:05:00 -0800] base         INFO     Selected cluster 0e83a448-26c9-459b-a0f2-3478ecb119af {u'interface': u'impala', u'namespace': u'0e83a448-26c9-459b-a0f2-3478ecb119af', u'type': u'direct', u'id': u'0e83a448-26c9-459b-a0f2-3478ecb119af', u'name': u'0e83a448-26c9-459b-a0f2-3478ecb119af'} interface hiveserver2
[04/Dec/2019 03:05:18 -0800] access       WARNING  10.126.49.92 -anon- - "POST /hue/accounts/login HTTP/1.1"-- Failed login for user: testuser

И, немного яснее:

perl -lne 'if(/^\[([^]]+)/){ ## skip lines that do not match
            ## Save the date of the current line as $d
            $d=$1; 
            ## Replace all slashes with pipes so the 'date' command
            ## can read this as a date.
            $d=~s|/| |g; 
            ## Now, translate $d into seconds since the epoch
            chomp($d=`date -d "$d" +%s`); 
            ## Set the threshold date in seconds since the epoch.
            chomp($dateThreshold=`date -d "04 Dec 2019" +%s`); 
            ## Print this line if its date is greater than or equal to the threshold
            print if $d >= $dateThreshold;
           } ' test.log 

Наконец, вы можете сделать его немного более эффективным, переместив шаг, устанавливающий порог, в блок BEGIN, чтобы он выполнялся только один раз при запуске скрипта:

perl -lne 'BEGIN{chomp($dateThreshold=`date -d "04 Dec 2019" +%s`); } if(/^\[([^]]+)/){$d=$1; $d=~s|/| |g; chomp($d=`date -d "$d" +%s`); print if $d >= $dateThreshold;} ' test.log 
0
27.01.2020, 21:58

с помощью sed:

sed -n "/$(date +'%d\/%b\/%Y')/,/*/p" test.log | grep -i "failed login"
  • печатает все после совпадения (даты ).

ПРИМЕЧАНИЕ. :Текущая дата должна быть доступна в файле журнала.

0
27.01.2020, 21:58

Вот еще один ответ, использующий GNU awk, который прибегает к вызову команды GNU date.

Программа awk(вызовемfind_after_timestamp.awk)вот так:

BEGIN{
    gsub("/"," ",start_datetime)
    extcmd=sprintf("date -d \"%s\" +\"%%Y %%m %%d %%H %%M %%S\"",start_datetime)
    extcmd | getline startstring
    close(extcmd)
    start_ts=mktime(startstring)
    print "Lines will be matched starting with timestamp",start_ts

    printf("Will look for: \"%s\"\n",searchpat)
}


{
    if (match($0,/^\[([[:print:]]*)\][[:print:]]*$/,line_datetime)==0) next
    gsub("/"," ",line_datetime[1])
    extcmd=sprintf("date -d \"%s\" +\"%%Y %%m %%d %%H %%M %%S\"",line_datetime[1])
    extcmd | getline line_dtstring
    close(extcmd)
    line_ts=mktime(line_dtstring)
    if (line_ts > start_ts && $0 ~ searchpat) print
}

Вы бы назвали это как

awk -v start_datetime="04/Dec/2019 02:05:21 -0800" -v searchpat="[Ff]ailed login" -f find_after_timestamp.awk test.log

Где переменная start_datetimeбудет началом вашего диапазона поиска, т. е. будут учитываться все записи с датой/временем, равным этому моменту времени или после него. Значение start_datetimeдолжно иметь тот же формат, что и в вашем лог-файле, но, кроме того, является произвольным и не обязательно должно быть значением, фактически присутствующим в файле. Переменная searchpatбудет содержать искомый шаблон.

Пояснение

  • Эта конструкция вращается вокруг преобразования вашей (скорее «не -стандартной» )спецификации даты/времени DD/MONTH/YYYY HH:MM:SS TIMEZONEво что-то, понятное GNU date, путем замены /в части даты на пробелы с использованием gsub.

  • Затем он вызывает внешнюю команду date, выполняя строку extcmdв оболочке и считывая результат в строковую переменную(startstringна этапе установки, line_dtstringна этапе разбора файла -), который теперь отформатирован так, чтобы встроенная функция awkmktimeмогла анализировать ist.

  • Команда mktimeпреобразует удобочитаемую -дату/время в числовое -UNIX-время, которое можно сравнивать с помощью арифметического сравнения.

  • В фазе BEGINэто делается для преобразования спецификации даты начала, в основной части это делается для преобразования временной метки, связанной с текущей строкой. Строки без метки времени будут игнорироваться(if (match(...)==0) next).

  • Если отметка времени текущей строки больше (= позже ), чем опорная отметка времени начала, И в строке найдено searchpat, строка будет напечатана.

Я знаю, что обращение к внешним программам в awkпрограмме вызывает неодобрение, но это поможет с базовыми инструментами, доступными практически при любой установке.

0
27.01.2020, 21:58

Теги

Похожие вопросы