Обсуждение статьи тематического каталога: Обработка log-файла почтового сервера Postfix (postfix log statistic)Ссылка на текст статьи: http://www.opennet.me/base/net/postfix_log_parse.txt.html
Так, мелкие замечания:
month varchar(10), day char(2) -почему не заменить на тип date имхо, разумнее, тем более парсинг не займет много времени %hash даст спасенье. Да и процес сравнения для MySQL пойдет легче и быстрее.
При мелкой нагрузке - тоесть редких выборках - такая база нормально дышать будет. При большой - активное составление отчетов и прочая... Касательно ключей - даже не знаю что сказать. Скорее разумнее сделать индексацию по rcpt_to и mail_from + size писем, введя в качестве primary key что-то типа id поля, с auto encrement. Почему так? Потому что ключами(индексами) надо делать поля по которым выбираются данные, а не те которые выбираются. Если педположить, что интересует конкретно время прохождения письма от pupkin@domen к vasia@domen2, тогда это разумно...Но здесь претензии скользки по определению - надо решать на этапе проектирование БД, что с ней делать будут.
А так в принципе, ничего...
Большое спасибо за замечания - учту в будущем!
Честно говоря это мой первый опыт самостоятельной работы с Perl-ом и MySQL-ем, к чему весьма способствовала Ваша статья:
http://www.opennet.me/base/net/ng_billing_letter.txt.html
Чтобы опыту набраться, можно и такие скрипты писать, для реальных же задач даже незнаю.
У меня на релее около 50к писем в день и около 2к пользователей которые эти письма пишут, но задачи возникают как правило:
1.) посмотреть доставилось ли письмо от одного пользователя к другому (в основном за сегодняшний день, и раза три было посмотреть за неделю)
2.) какие письма были от такого то пользователя и кому
3.) сколько спама и вирусов отсеилось
4.) какой общий объем почты ушел и пришел.1,2,3 решаются с помощью простых sh скриптов (4 строчки скрипт), время выполнения которых до 10 сек
3,4 решаются с помощью pflogsumm
Согласен с AlgorКогда логи сервака занимают по 300-400 метров в день, особо с БД не поработаешь. Plain-text парсить гораздо эффективнее с точки зрения использования ресурсов системы.
Я даже не представляю, сколько perl отожрет памяти, если ему скормить достаточно большой лог.
А может Вы проверите эту программу на своих логах и сообщите результат?У меня такого трафика нет, к сожалению :)
Я тестировал эту программу на логах в 2 Мб и 25 Мб. Без записи в БД, со сбросом информации в файл:
./maillogs > mail.txt эта программа отрабатывала лог за 2 секунды (увеличение размера лога в 10 раз на скорости не сказалось).Был бы очень признателен, если ы кто-нибудь протестировал прогу на больших журналах.
to Vershinin EgorПрогоню попробую...
Но смысла в этом нет. Для больших логов гораздо нужнее утилиты выбора конкретной информации (поиск следов конкретного письма).
Кстати, сколько занимает база для лога в 25 мегабайт?
Примерно 450 кб
1. Интересно как поведет себя скрипт, если в конец файла /var/log/maillog будут дописываться данные, и смогут ли они туда вобще дописываться при открытом файле.
2. Выполнение скрипта лучше поставить в logrotate, а не в cron, и после того как журнал ротэйтнулся, тогда первый вопрос отпадает сразу.
to Vershinin Egorниче он у меня в логах не обнаружил:
21.03.2006 23:59:59 KRAT xxx.xxx.xxx [info] postfix/qmgr[11146]: [ID 197553 local1.info] 814DB24912: removedпробежался по файлу и все
это все из-за split на самом деле, формат логов может разниться, поэтому нехорошо привязываться к своему логу
прогнал я скрипт с большим логом (310Mб)памяти сожрал во время выполнения 128Мб (благо отдал потом :))) )
работал 3 минуты, загрузив тазик на 90% (остальные 10% делили между собой иксы и gkrellm)Итого:
чисто текстовые данные по письмам (дата, время, отправитель, адресат, размер) составили около 6.5Мб
если принять размер одной записи в БД за 500 байт (примерная взятая почти с потолка цифра, хотя всякое может быть), то занимать мой лог будет около 50Мб.Теперь к основному... товарищ Vershinin Egor, основным недостатком Вашего скрипта является оторванность от postfix как ни странно.
Вот короткий пример:
$ tail -10000 ./postfix-2006-03-21 | grep 438B324958:
21.03.2006 23:59:38 KRAT xxx.xxx.xxx [info] postfix/smtpd[11195]: [ID 197553 local1.info] 438B324958: client=unknown[85.136.42.194]
21.03.2006 23:59:40 KRAT xxx.xxx.xxx [info] postfix/cleanup[11154]: [ID 197553 local1.info] 438B324958: message-id=<720101c64cf4$e689a770$be710e0a@knee>
21.03.2006 23:59:44 KRAT xxx.xxx.xxx [info] postfix/qmgr[11146]: [ID 197553 local1.info] 438B324958: from=<info@lopez.org>, size=10647, nrcpt=2 (queue active)
21.03.2006 23:59:44 KRAT xxx.xxx.xxx [info] postfix/smtp[13443]: [ID 197553 local1.info] 438B324958: to=<rel@domain>, relay=localhost[127.0.0.1], delay=7, status=sent (250 Ok: queued as 88E1124938)
21.03.2006 23:59:44 KRAT xxx.xxx.xxx [info] postfix/smtp[13443]: [ID 197553 local1.info] 438B324958: to=<ttv@domain>, relay=localhost[127.0.0.1], delay=7, status=sent (250 Ok: queued as 88E1124938)
21.03.2006 23:59:44 KRAT xxx.xxx.xxx [info] postfix/qmgr[11146]: [ID 197553 local1.info] 438B324958: removedНе будем обращать на то, что отправлено было все на localhost. Посмотрим только на то, что письмо ушло 2 (двум!) адресатам... И что в этом случае скрипт посчитает?
$ tail -1000 ./log | grep 85.136.42.194
21.03.2006,23:59:38,85.136.42.194,info@lopez.org,ttv@domain,10647Т.е. мы посчитали только письмо для последнего адресата... И даже если не вспоминать про такие важные вещи, как количество соединений с одного IP (подсети и пр.), количество попыток отправки почты - про все то, что данный скрипт игнорирует - все равно получается, что функции свои он не выполняет.
А переделка его, например, для обработки нескольких rcpt to на одно письмо сразу влечет к увеличению расходуемой памяти, может быть циклов обработки лога и пр.
Короче, дорого, коряво и неэффективно.
P.S.
Vershinin Egor, мне самому приходилось писать подобные скрипты для анализа работы сервера. получалось немногим лучше (если не хуже в некоторых задачах).
Хранить статистику в БД разумно, логи - нет (у Вас получается хранение чего-то среднего). Опытным путем пришел к тому, что необходимо иметь набор шаблонов grep для фильтрации интересующей меня информации из лога и еще набора специализированных скриптов для ее анализа. Это позволяет решать как текущие задачи администрирования, так и получать статистику.
>P.S.
>Vershinin Egor, мне самому приходилось писать подобные скрипты для анализа работы сервера.
>получалось немногим лучше (если не хуже в некоторых задачах).
>Хранить статистику в БД разумно, логи - нет (у Вас получается хранение
>чего-то среднего). Опытным путем пришел к тому, что необходимо иметь набор
>шаблонов grep для фильтрации интересующей меня информации из лога и еще
>набора специализированных скриптов для ее анализа. Это позволяет решать как текущие
>задачи администрирования, так и получать статистику.
Ну зачем же так человека расстраивать...:) Все же вектор напрвлености нужно задать правильный. Да и те скрипты и бинарники, которыми выпользуетесь начинались с такого же. Только разница в том, что они пользуют временные файлы, а не таблицы. Касательно же сабжа, то здесь гораздо важнее правильно организовать структуру БД и таблиц. То бишь, к чему я веду. Лог в случае его хранения в БД ни вкоем случае нельзя ложить в обну таблицу. Минимум две. Потому что при выборках из таблиц нарушается самый главный принцип БД. В одной ячейке находиться куча данных, которые повторяются. Кстати в этом плане показателен exim, который хранит свой лог в трех файлах. К чему бы это? :) (так наводящая шутка в сторону)
Второе. Для риалтайма статистики необходимо вешать pipe на лог или еще какой изврат придумывать. Объясню зачем - что бы уменьшить нагрузку на проц/память в процессе предварительного парсинга лога и раскидывании по таблицам. Многие данные надо просто банально продумать на начале проектирования. То есть сесть с логом типичным. Хотя бы на 50-100 строк. Посмотреть какие данные проходят. что надоть, что нет. Взять лист бумаги и нарисовать таблички. Потом связи между ними. Взять еще один и снова. Но уже на основе предыдущего. И так до тех пор, пока у вас не окажетьсяв итоге несколько таблиц. в которых будут присутсвовать минимум данных. и минимум будет повторятся. Плюс доводите до того, что бы всякие varchar сводились тоже к минимуму. Например смысл присутствия имя hostname если его можно заменить на 1, введя дополнительно таблицу:
+--+---------+
|id| hostname|
+--+---------+
| 1|server.ua|
+--+---------+
| 2|server.ru|
+--+---------+Даже в случае если используется только один сервер какой прирост, плюс уменьшение объема места, засчет использования не 4-х байт, а 2-х, например (точно размерность не вспомню для varchar и того же smallint).
Введение правильных ключей при частых выборках, а не раз впятилетку, позволит добиться того, что если например при выполнении первого запроса выборка шла 5 минут, то второй пробежиться за минуту. На что я выше кстати уже указал.
Еще раз возвращаясь к структуре таблицы primary key(month,day,time) все же выбран неудачно, так как нагрузка у автора явно маленькая и письма ходят редко, то ему оно подойдет, а вот на больших объемах нет - так как очень часто primary key будет повторятся, соответственно в базу данные попадать не будут (дублирование primary невозможно по определению).
ТО есть, Женя, Мысль у тебя хорошая. И даже нужная. Только еще сырая. Я сам такую гадость сейчас пишу. Только я пишу не единичную, а суммарную для нескольких серваков. Потому так и разжевываю, что и зачем. Касательно предыдущих ораторов, того же Сергея, могу сказать, что скорее всего статистику они генерят один раз и забывают об этом. Если тебе нужен именно такой вариант, то то, что ты написал, действительно не имеет смысла, если нужно, что-то более серьезное - тогда продолжай копать.
Для меня такая проблема встала, когда пришлось частенько парсить логи нескольких почтовиков, при чем у каждого он разросся от полутора до 2-х с половиной гигов. И просто статистика типа сколько от и до пользователя прошло писем мне была не нужна. Мне нужны были данные, как прошло конкретное письмо в конкретном интервале времени,возможность вернуть лог полностью и касательно одного письма, и т.д. А это уже слишком специфичные задачи и большинству они нафиг не нужны.
Извини, не Женя, а Егор. :)
>Касательно же сабжа, то здесь гораздо важнее правильно
>организовать структуру БД и таблиц.
Всеми руками-ногами присоединяюсь.>Еще раз возвращаясь к структуре таблицы primary key(month,day,time) все же выбран неудачно,
>так как нагрузка у автора явно маленькая и письма ходят редко,
> то ему оно подойдет, а вот на больших объемах нет
>- так как очень часто primary key будет повторятся, соответственно в
>базу данные попадать не будут (дублирование primary невозможно по определению).
>ТО есть, Женя, Мысль у тебя хорошая. И даже нужная. Только еще
>сырая. Я сам такую гадость сейчас пишу. Только я пишу не
>единичную, а суммарную для нескольких серваков. Потому так и разжевываю, что
>и зачем. Касательно предыдущих ораторов, того же Сергея, могу сказать, что
>скорее всего статистику они генерят один раз и забывают об этом.
Конечно, почти так. Точнее, интересующую меня статистику можно получать другим путем. Так, собрать данные о размерах писем проще в контент фильтре, если он это умеет, а если не умеет, но умеет со внешними модулями работать - то написать такой модуль. На эту тему можно долго говорить, но это будет все же немного офтоп.>Для меня такая проблема встала, когда пришлось частенько парсить логи нескольких почтовиков,
>при чем у каждого он разросся от полутора до 2-х с
>половиной гигов. И просто статистика типа сколько от и до пользователя
>прошло писем мне была не нужна. Мне нужны были данные, как
>прошло конкретное письмо в конкретном интервале времени,возможность вернуть лог полностью и
>касательно одного письма, и т.д.
Ага, вот это как "прямое" назначение логов :))) я рад просто, что у меня они не по 2 гига, и что это требуется не особо часто, иначе пришлось бы так же, как и Вы поступать. А так можно особо не напрягаясь скриптами управится.>А это уже слишком специфичные задачи и большинству они нафиг не нужны.
Золотые слова. На задачу же и решалка :)
Здравствуйте товарищи!а как можно брать каждные 2 минуты и вставлять их в таблицу?
пример:
1) открывайт файло логов
2) блокируем файл для записи других прграмм
3) переносим в СУБД
4) очищаем файл
5) разблориуем файлтакая схема реализации подойдет?
или нужно синхронизировать с помощью XML ?или еще как-то можно?
синхронизировасть с помощю дампа с Storable наверное надо...
Я у себя сдела primary key
month
day
time
mailfrom
rcptto,
а то иначе теряются записи,(при вставке указывает на дублирующие записи), так как за секунду может быть несколько писем., Также в таблицу не вносятся записи, если письмо посылалось копией кому-либо еще.
при обработке выдает
DBD::mysql::st execute failed: Column 'month' cannot be null at ./log.pl line 55.
Что делать то???
to Avolon:
попробуй убери $rec{$id}->{'client'} ne '127.0.0.1'
вместо етого ип пропиши како-то левый...
подскажите как етот скрипт изменить, что бы можно было и статус письма из логов получить?
mail.log примерно 415 метров
отработал приблизительно за минуты 3
Спасибо!
как добавить год? нужно чтобы в базу писался в отдельную колонку год. Никак не могу разобраться.