Получить записи файла журнала между двумя датами, только фатальные - PullRequest
0 голосов
/ 26 июня 2018

Я искал в Интернете, ТАК и ничего не хочет делать эту работу. Имеется простой лог-файл apache, такой как

[Fri Jun 22 11:46:13 2018] [error] [client xxxxxxxx] PHP Parse error:  syntax error, unexpected end of file in yyyyyyyyyyyyyyyyy on line 3554, referer: wwwwwwwwwwwwwwwwwwwwwwww
[Fri Jun 22 14:09:37 2018] [error] [client xxxxxxxx] PHP Fatal error:  Call to undefined function date_mysql2german() in yyyyyyyyyyyyyyyyy on line 156, referer: wwwwwwwwwwwwwwwwwwwwwwww
[Mon Jun 25 17:03:37 2018] [error] [client xxxxxxxx] PHP Warning:  mysql_num_rows() expects parameter 1 to be resource, null given in yyyyyyyyyyyyyyyyy on line 1409, referer: wwwwwwwwwwwwwwwwwwwwwwww
[Tue Jun 26 11:46:26 2018] [error] [client xxxxxxxx] PHP Warning:  mysql_num_rows() expects parameter 1 to be resource, boolean given in yyyyyyyyyyyyyyyyy on line 9390, referer: wwwwwwwwwwwwwwwwwwwwwwww
[Tue Jun 26 11:46:26 2018] [error] [client xxxxxxxx] PHP Warning:  mysql_num_rows() expects parameter 1 to be resource, boolean given in yyyyyyyyyyyyyyyyy on line 9432, referer: wwwwwwwwwwwwwwwwwwwwwwww

Мне нужно извлечь все строки «Предупреждение PHP:» (полная строка) за последние 5 минут.

Вот что я пробовал до сих пор

awk 
-v Date="$(date "+[%a %b %d %H:%M:%S %Y")" \ 
-v Date2="$(date --date="5 minutes ago" "+[%a %b %d %H:%M:%S %Y")" \
'$4 > Date && $4 < Date2' /var/log/apache2/apache2/my_log_file.log

Но даже это (без grep, например, для "Warning") ничего не возвращает. Вставленные записи в журнале и их дата / время являются лишь примерами - на самом деле у меня есть предупреждения за последние 5 минут, поэтому он должен что-то определенно вернуть.

Есть идеи, как изменить этот материал и заставить его работать? заранее спасибо Alex

Ответы [ 2 ]

0 голосов
/ 27 июня 2018

Это сработало в bash + gawk для меня:

#!/bin/bash

LC_ALL=C gawk -v limit=$(date --date="5 minutes ago" "+%s") '
function epoch(month, day, hhmmss, year) {
    gsub(/:/, " ", hhmmss)
    sub(/\]/, "", year)
    month = (index("JanFebMarAprMayJunJulAugSepOctNovDec", month) + 2) / 3
    return mktime(year" "month" "day" "hhmmss)
}
/PHP Warning/ && epoch($2, $3, $4, $5) > limit
' "test.log"

Если вы также хотите включить фатальные ошибки, просто удалите /PHP Warning/ && или настройте регулярное выражение по своему усмотрению (например, /Warning|error/ или подобное).

0 голосов
/ 26 июня 2018

Проблема в том, что вы сравниваете свои строки слишком буквально. Даты упорядочены по данным, но awk сравнивает лексикографическое («январь» <«февраль» для даты, но для строки это не так). Здесь можно использовать различные подходы, но я предлагаю сделать сравнение в эпоху UNIX. </p>

$ tend=$(date "+%s")
$ tstart=$(date --date="5 minutes ago" "+%s")
$ awk -F '[][]' '!/PHP Warning/{next}
                 { cmd="date --date=\""$2"\" \"+%s\""
                   time=((cmd | getline line) > 0 ? line : -1)
                   close(cmd) }
                 (time == -1) { exit 1 }
                 (tend <= time && time <= tstart)
                ' tstart=$tstart tend=$tend <logfile>

примечание: будет выполнено большое количество вызовов на date, если ваш файл большой.

Другим подходом может быть вызов mktime из GNU awk или переформатирование вашей временной строки в ггггммдд ЧЧММСС . Это позволяет использовать лексикографический порядок для строк:

$ tstart=$(date -d="5 minutes ago" "+%Y%m%d%H%M%S"")
$ tend=$(date "+%Y%m%d%H%M%S"")
$ awk 'BEGIN{ month["Jan"]="01"; month["Feb"]="02"; month["Mar"]="03"
            month["Arp"]="04"; month["May"]="05"; month["Jun"]="06"
            month["Jul"]="07"; month["Aug"]="08"; month["Sep"]="09"
            month["Oct"]="10"; month["Nov"]="11"; month["Dec"]="12" }
      !/PHP Warning/{next}
      { time=$4; gsub(/:/,"",time); year=substr($5,1,4);
        date=sprintf(%4s%2s%0.2d%6s,year,month[$2],$3,time) }
      }
      (tstart <= date && tend <= date)
     ' tend=$tend tstart=$tstart  <logfile>

Или по предложению Эд Мортон :

$ awk '!/PHP Warning/{next}
       { year=substr($5,1,4)
         month=(index("JanFebMarAprMayJunJulAugSepOctNovDec",$2)+2)/3
         time=$4; gsub(/:/,"",time);
         date=sprintf(%4s%0.2d%0.2d%6s,year,month,$3,time)
       }
       (tstart <= date && tend <= date)
      ' tend=$end tstart=$tstart <logfile>

Соответствующее сообщение можно найти здесь: Regex для соответствия форматам даты в лог-файле

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...