Анализатор логов Apache своими руками и в одну строчку
О невероятной силе командной строки пост.
Мне приходится поддерживать работоспособность некоторых сайтов и одной из ключевых процедур в этом деле является выявление паразитного трафика и борьба с ним. Почти все CMS позволяют зафиксировать аномальные перегрузки и вычислить их источник. Иногда приходится делать хитрые запросы к СУБД. Но в сложных ситуациях приходится опускаться по уровням абстракции еще ниже и «листать» системные журналы web-сервера. Недавно как раз столкнулся с таким случаем.
Задача: есть журнал access.log размером около 300 Мб. Требуется быстро вычислить первую десятку IP, с которых поступило больше всего запросов.
Решение: поставить анализатор логов типа Webalizer или Awstat.
Так я и собирался поступить, но для этих систем сбора статистики требуется настраивать сервер, в них регулярно находят дырки, замедляется работа всего компа. Самое главное, посмотреть статистику требуется только 1 раз и ставить тяжелые пакеты для обработки и визуализации логов не хотелось.
Тогда я решил, что проще и быстрее написать свой скрипт. Я лучше всего знаю Ruby, поэтому его и решил использовать. Алгоритм:
- читаем весь лог в память;
- разбиваем по строкам;
- каждую строку разбиваем на подстроки по регулярному выражению;
- каждый IP (первый столбец каждой строки) является ключом хеша и значение увеличивается на 1 при каждом вхождении IP;
- сортируем хэш по убыванию ключа;
- печатаем первую десятку;
- PROFIT!
Кинулся писать и почти сразу же вспомнил о команде cut. Можно же вычленить IP из всего лога одной командой. Записываю для интереса:
cat $1 | cut -d " " -f 1
Сразу приходит мысль: надо отсортировать, чтобы одинаковые IP шли друг за другом:
cat $1 | cut -d " " -f 1 | sort
Теперь самое время вспомнить о команде uniq. С помощью man освежаем в памяти детали и вспоминаем любопытную опцию -с, позволяющую не только оставить уникальные IP, но и подсчитать количество повторов:
cat $1 | cut -d " " -f 1 | sort | uniq -c
Получаем две колонки: в первой количество запросов с одного IP, в другой — сам IP. Но есть два минуса. Данные отсортированы по IP, а не по количеству повторов. Во-вторых, данных очень много, десятки тысяч строк и все вперемежку. Самое время снова применить sort. Надо лишь заставить sort воспринимать первый столбец как числа и сортировать в обратном порядке. Оказывается, и такие опции предусмотрены: -n и -r.
cat $1 | cut -d " " -f 1 | sort | uniq -c | sort -n -r
Отлично, но данных слишком много, а нам надо только первые 10. Тут даже домохозяйки и приравненные к ним пользователи Ubuntu вспомнят о существовании команды head. Добавляем и ее в общий конвейер и получаем окончательный вариант:
cat $1 | cut -d " " -f 1 | sort | uniq -c | sort -n -r | head -n 10
Получаем именно то, что нужно, причем без всякого стороннего софта и программирования. Данный пример раскрывает одно из самых сильных преимуществ интерфейса командной строки.
А что дальше?
Дальше комбинируем с командами mail и whois, добавляем скрипт в cron и начинаем получать каждодневные отчеты в удобной форме на email. Никогда еще банить малолетних каккеров не было так приятно. ;)
Комментарии
pomodor
30 января, 2015 - 16:28
Можно было бы, конечно, сразу передавать IP в iptables, если количество повторов превышает заданный уровень, но так можно случайно забанить поисковых ботов.
Комментировать