Я кодировал некоторый 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 строки являются «входом». Я довольно озадачен этим.
С уважением,
Мэтью О.
Это может помочь:
#!/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
для больших файлов журнала. К сожалению, я не смог проверить большие файлы журнала в моей среде. Я думаю, это должно быть хорошо для файлов размером несколько мегабайт.
Заметки: Я предположил, что —
Редактировать:
Включая предложение @ 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)
Других решений пока нет …