Удаление избыточных записей в журнале доступа

Я кодировал некоторый php-скрипт для веб-страницы в нашей компании, и он записывает ip-адрес, дату и время каждого посетителя, а также внедряет cookie в браузер клиентов, чтобы отслеживать количество посещений за всю жизнь. Он печатает всю эту информацию в журнал доступа в этом формате.

Visitor IP: 173.11.250.189
Date = Wednesday 12-23-2015
Time = 09:47:16am
# of Visits:1

Visitor IP: 173.11.250.189
Date = Wednesday 12-23-2015
Time = 09:47:40am
# of Visits:2

Visitor IP: 173.11.250.189
Date = Wednesday 12-23-2015
Time = 09:47:46am
# of Visits:3

Visitor IP: 173.11.250.192
Date = Wednesday 12-23-2015
Time = 09:57:40am
# of Visits:1

Visitor IP: 173.11.250.192
Date = Wednesday 12-23-2015
Time = 09:57:54am
# of Visits:2

Visitor IP: 173.11.250.189
Date = Wednesday 12-23-2015
Time = 10:20:04am
# of Visits:4

Visitor IP: 173.11.250.176
Date = Wednesday 12-23-2015
Time = 10:20:32am
# of Visits:1

Если if cookie присутствует = false, то он просто вводит новый cookie со значением 1 и печатает значение по умолчанию 1 в журнале доступа.

Раз в неделю у меня есть задание cron, которое запускает скрипт, который отправляет этот журнал мне и владельцам компании по электронной почте, затем он создает архив этого журнала и, наконец, очищает журнал и начинает заново.

Это прекрасно работает за исключением одного факта …. избыточные записи.
Я пытаюсь найти способ удалить избыточность в этом журнале, прежде чем он будет отправлен по электронной почте владельцам и мне. Так, например, две записи, перечисленные выше, имеют один и тот же IP-адрес, но отмечают два отдельных посещения. С избыточными записями я хотел бы сохранить запись с наибольшим числом посещений, удаляя избыточные записи, которые содержат меньшее количество посещений.

Отфильтрованный вывод приведенного выше образца будет выглядеть примерно так:

Visitor IP: 173.11.250.189
Date = Wednesday 12-23-2015
Time = 10:20:04am
# of Visits:4

Visitor IP: 173.11.250.192
Date = Wednesday 12-23-2015
Time = 09:57:54am
# of Visits:2

Visitor IP: 173.11.250.176
Date = Wednesday 12-23-2015
Time = 10:20:32am
# of Visits:1

Там, где хранятся только данные о самых последних посещениях, и где было найдено несколько посещений с одного и того же IP, он сохранял только самые последние записи, которые имели более высокое значение для числа посещений.

Есть идеи?

Я действительно не смог придумать каких-либо решений из-за того, что для фильтрации необходимо учитывать 4 строки за раз, а не только построчную фильтрацию, поскольку каждые 4 строки являются «входом». Я довольно озадачен этим.

С уважением,
Мэтью О.

2

Решение

Это может помочь:

#!/bin/bash
# Records are separated by blank lines.
# Each line is one field.

sed -n '{1!G;h;$p}' $1 | awk 'BEGIN {RS="";FS="\n";OFS="\n";ORS="\n\n"}
{
if(!seen[$4]++)
{
print $4,$3,$2,$1
}
}'

Сохранить скрипт как RedundantRecordRemover сделать его исполняемым,
и запустить его как:

./RedundantRecordRemover your_log_file

Фактически вы можете заменить исходный файл на:

./RedundantRecordRemover your_log_file >> tempfile ; mv tempfile your_log_file

Идея:

sed скрипт переворачивает текст из файла, который вы ему передали, прежде чем передать его awk скрипт. Этот разворот текста полезен при нацеливании на последнюю запись для каждого IP-адреса.

Требование:

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

Downfall:

Там может быть speed bottleneck для больших файлов журнала. К сожалению, я не смог проверить большие файлы журнала в моей среде. Я думаю, это должно быть хорошо для файлов размером несколько мегабайт.

Заметки: Я предположил, что —

  1. последнее появление IP в журнале действительно является последним. Что ж! это файл журнала в конце концов.
  2. порядок, в котором IP-адреса перечислены в выходном файле, совсем не важен, если не нужно делать еще несколько настроек.

Редактировать:

Включая предложение @ fedorqui, можно написать еще один способ написания сценария:

#!/bin/bash
# Records are separated by blank lines.
# Each line is one field.

awk 'BEGIN {RS="";FS="\n";OFS="\n";ORS="\n\n"}
{
if(!seen[$4]++)
{
print $4,$3,$2,$1
}
}' <(tac $1)
1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]