Vincent1
@Vincent1

Как посчитать число строк в файле по условию?

Нужно посчитать количество новых строк в логе за последние 24 часа, которые содержат `router.php`.
Сейчас я это делаю так:
cat example.com.log | grep "router" | wc -l
Но в таком варианте не учитывается дата. Как добавить дату в условию поиска?
пример записи в журнале
66.249.70.79 - - [17/Nov/2021:15:15:56 -0500] "GET /router.php HTTP/1.0" 301 274 "-" "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 5X Build/MMB29P) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Mobile Safari/537.36 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"
  • Вопрос задан
  • 552 просмотра
Решения вопроса 2
xotkot
@xotkot
хорошо есть и хорошо весьма
если знать точные даты начала и конца то легко:
awk '/router.php/' example.com.log | awk '/\[16\/Nov\/2021:15:15:56 -0500\]/,/\[17\/Nov\/2021:15:15:56 -0500\]/' | wc -l


п.с.
если делать конкретно через date, а не тупо обрабатывать как строки что проще но нужно знать конкретный диапазон, то необходимо учитывать некоторые нюансы, ту же локаль, так как у вас или кого-то другой кто будет у себя запускать данную команду может быть отличная локаль для даты чем в самом логе
сравните
$ date -d now
$ LANG=ru_RU.UTF-8 date -d now
$ LANG=en_US.UTF-8 date -d now

сами локали естественно должны быть доступны в системе, проверить можно утилитой localectl:
$ localectl list-locales
en_US.UTF-8
ru_RU.UTF-8


также +0300 это не просто так, и если обрабатывать скрипт находясь в другом часовом поясе то может произойти смещение по времени в ту или иную сторону
так что если внести поправки на часовой пояс( %z) + локаль, получим:
LANG=en_US.UTF-8 date -d 'now-24hours' +'[%d/%b/%Y:%H:%M:%S %z]'


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

cat example.ru.log  | awk -F'[][/:]' '/router.php/{"date +%s -d \""$2"-"$3"-"$4" "$5":"$6":"$7"\"" | getline z; print z" "$0}'

здесь мы преобразовали к понятному date формату, а потом перевели в юникс время( +%s) и получившейся результат просто добавили к началу строки.
результат

1637320437 212.193.33.123 - - [19/Nov/2021:14:13:57 +0300] "GET /router.php HTTP/1.0" 301 445 "-" "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 5X Build/MMB29P) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Mobile Safari/537.36 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"
1637320437 212.193.33.123 - - [19/Nov/2021:14:13:57 +0300] "GET /router.php HTTP/1.0" 301 445 "-" "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 5X Build/MMB29P) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Mobile Safari/537.36 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"
1637320438 212.193.33.123 - - [19/Nov/2021:14:13:58 +0300] "GET /router.php HTTP/1.0" 301 449 "-" "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 5X Build/MMB29P) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Mobile Safari/537.36 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"
1637321647 212.193.33.123 - - [19/Nov/2021:14:34:07 +0300] "GET /router.php HTTP/1.0" 301 449 "-" "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 5X Build/MMB29P) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Mobile Safari/537.36 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"
1637321647 212.193.33.123 - - [19/Nov/2021:14:34:07 +0300] "GET /router.php HTTP/1.0" 301 447 "-" "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 5X Build/MMB29P) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Mobile Safari/537.36 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"
1637321648 212.193.33.123 - - [19/Nov/2021:14:34:08 +0300] "GET /router.php HTTP/1.0" 301 446 "-" "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 5X Build/MMB29P) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Mobile Safari/537.36 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"
1637321650 212.193.33.123 - - [19/Nov/2021:14:34:10 +0300] "GET /router.php HTTP/1.0" 301 445 "-" "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 5X Build/MMB29P) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Mobile Safari/537.36 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"
1637321650 212.193.33.123 - - [19/Nov/2021:14:34:10 +0300] "GET /router.php HTTP/1.0" 301 451 "-" "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 5X Build/MMB29P) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Mobile Safari/537.36 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"
1637321651 212.193.33.123 - - [19/Nov/2021:14:34:11 +0300] "GET /router.php HTTP/1.0" 301 445 "-" "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 5X Build/MMB29P) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Mobile Safari/537.36 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"
1637324092 212.193.33.123 - - [19/Nov/2021:15:14:52 +0300] "GET /router.php HTTP/1.0" 301 449 "-" "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 5X Build/MMB29P) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Mobile Safari/537.36 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"
1637326108 212.193.33.123 - - [19/Nov/2021:15:48:28 +0300] "GET /router.php HTTP/1.0" 301 447 "-" "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 5X Build/MMB29P) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Mobile Safari/537.36 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"
1637327153 212.193.33.123 - - [19/Nov/2021:16:05:53 +0300] "GET /router.php HTTP/1.0" 301 446 "-" "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 5X Build/MMB29P) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Mobile Safari/537.36 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"


дату 1 день(24 часа) назад можно узнать так:
date +%s -d 'now-1day'
или даже так
echo $[`date +%s` - 24*60*60]
просто отняв от текущего количество нужных секунд

в итоге получим:
cat example.ru.log |awk -F'[][/:]' '/router.php/{"date +%s -d \""$2"-"$3"-"$4" "$5":"$6":"$7"\"" | getline z; print z" "$0}' | awk -v t=$[`date +%s` - 24*60*60] '$1>=t'


теперь при желании можно легко расширить и указывать диапазон поиска от(t1) и до(t2)
cat example.ru.log |awk -F'[][/:]' '/router.php/{"date +%s -d \""$2"-"$3"-"$4" "$5":"$6":"$7"\"" | getline z; print z" "$0}' | awk -v t1=`date +%s -d '19-Nov-2021 15:00:00 +0300'` -v t2=`date +%s -d '19-Nov-2021 16:00:00 +0300'` '$1>=t1 && $1<=t2'

здесь ищем в диапазоне одного часа
от 19-Nov-2021 15:00:00 +0300
до 19-Nov-2021 16:00:00 +0300
результат
1637324092 212.193.33.123 - - [19/Nov/2021:15:14:52 +0300] "GET /router.php HTTP/1.0" 301 449 "-" "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 5X Build/MMB29P) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Mobile Safari/537.36 (compatible; Googlebot/2.1; +www.google.com/bot.html)"
1637326108 212.193.33.123 - - [19/Nov/2021:15:48:28 +0300] "GET /router.php HTTP/1.0" 301 447 "-" "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 5X Build/MMB29P) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Mobile Safari/537.36 (compatible; Googlebot/2.1; +www.google.com/bot.html)"
Ответ написан
Vincent1
@Vincent1 Автор вопроса
cat example.ru.log | grep "router.php" | awk -vDate=`date -d'now-24 hours' +[%d/%b/%Y:%H:%M:%S` '$4 > Date {print Date, $0}' | wc -l
Думаю тут еше можно оптимизировать запрос, сделав все через awk.
Ответ написан
Пригласить эксперта
Ответы на вопрос 2
sotvm
@sotvm
Умный поймёт, а дураку и так всё равно.
так же, но добавь ещё греп даты через "трубу", а уже потом считай
типа так:
cat example.com.log | grep "17/Nov/2021" | grep "router" | wc -l

зы
хочешь несколько дат? грепай через grep -E
egrep -w 'first_DATA|second_DATA' или аналогичное grep -ew 'first_word|second_word'
не забывай экранировать спецсимволы
Ответ написан
saboteur_kiev
@saboteur_kiev
software engineer
Получаем примерную дату за последние сутки с нужной точностью
olddate=$(date -d "-24 hours" "+%d/%b/%Y:%H:%M:%S")
Но тут есть проблема. Если в данную секунду в прошлом не было ни одной записи, мы пролетим мимо. Поэтому округлим хотя бы до часа, но все равно остается риск, если приложение было выключено целый час, то мы не найдем начальную позицию вообще. Как эту проблему решать я не знаю, зависит от того что у вас в файле всегда будет что-то или не всегда и если не всегда, тогда все усложняется. Но давайте пойдем от простого, просто округлить хотя бы до часа:
olddate=$(date -d "-24 hours" "+%d/%b/%Y:%H")

Потом через sed можно найти текст от указанной даты и до конца файла, и тут же фильтруем router:
sed -nE "/$olddate/,\${/router/p}" file.log|wc -l

Ну или однострочник
sed -nE "/$(date -d "-24 hours" "+%d/%b/%Y:%H")/,\${/router/p}" file.log|wc -l
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

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