The OpenNET Project / Index page

[ новости/++ | форум | wiki | теги ]

Обработка log-файла почтового сервера Postfix (postfix log statistic)


<< Предыдущая ИНДЕКС Правка src / Печать Следующая >>
Ключевые слова: postfix, log, statistic,  (найти похожие документы)
From: Вершинин Егор <vershinin.e@gmail.com.> Newsgroups: email Date: Mon, 3 May 2006 14:31:37 +0000 (UTC) Subject: Обработка log-файла почтового сервера Postfix У многих системных администраторов, работающих с почтовыми серверами, рано или поздно возникают различные задачи, связанные с обработкой журнальных файлов. Например: 1) Нужно узнать было ли когда-то в прошлом письмо с определенного почтового адреса? 2) Или нужно посмотреть статистику работы с почтой уволившегося сотрудника? 3) Получить точный размер почтовых сообщений, прошедших через SMTP-сервер. 4) Да мало ли что еще Основные проблемы при таких задачах следующие: 1) При больших объемах почтового трафика журналы растут достаточно быстро; 2) Журналы подвергаются ежедневной ротации; 3) В журналах масса ненужной информации. Конечно, можно подстраховаться, и архивировать все ежедневные журналытолько вот зачем? Если возникнет задача снять статистику за год, то нужно будет выделять нужную информацию из 365 файлов (в случае ежедневной ротации), а нужной информации может быть всего несколько строк. Мною предлагается следующее решение этой проблемы: Ежедневно перед ротацией журнального файла обрабатывать файл Perl-скриптом и помещать нужную нам информацию в СУБД MySQL. Система, на которой решалась эта задача: FreeBSD 5.4, MySQL 4.1.16, Perl 5.8.6, Postfix 2.2.8, также установлен модуль: p5-DBI-1.5. 1) Создаем в СУБД MySQL базу данных maillogs с таблицей mails: Mysql> create database maillogs; Query OK, 1 row affected (0.11 sec) Mysql> create table mails( month varchar(10), day char(2), time time, ip varchar(255) not null default '', mailfrom varchar(255) not null default '', rcptto varchar(255) not null default '', size int, primary key(month,day,time)); Query OK, 0 rows affected (0.04 sec) Наша созданная таблица содержит 7 столбцов: month - Месяц, day - День, time - Время, ip - IP-адрес SMTP-клиента, mailfrom - почтовый адрес отправителя, tcptto - почтовый адрес получателя, size - размер сообщения. Естественно количество полей может меняться в зависимости от того, какие задачи ставит перед собой системный администратор. Для моих задач этих данных более чем достаточно. 2) Создаем пользователя для доступа к созданной базе: Mysql> grant select,insert,update on maillogs.* to mailuser@localhost identified by 'mailuser'; Query OK, 0 rows affected (0.06 sec) Mysql> flush privileges; Query OK, 0 rows affected (0.02 sec) 3) Самое главное - создаем скрипт на Perl, который будет обрабатывать наш журнальный файл, и помещать нужную информацию в СУБД MySQL: #!/usr/local/bin/perl use DBI; $dbh = DBI->connect("DBI:mysql:host=localhost;database=maillogs","mailuser","mailuser") or die "Нет доступа к СУБД!"; $insert = "INSERT INTO mails (month,day,time,ip,mailfrom,rcptto,size) VALUES(?,?,?,?,?,?,?)"; $sth = $dbh->prepare("$insert"); my %rec; open(MAIL, "/var/log/maillog"); while ($line = <MAIL>) { my ($month, $day, $time, $hostname, $servicename, $id, $message) = split /\s+/, $line, 7; if ($id =~ /([a-z0-9]+)\:/i) { $id = $1; $rec{$id} = {} unless ($rec{$id}); if ($message =~ 'removed') { $rec{$id}->{'removed'}++; } else { while ($message =~ /(client|size|from|to)=(\S+?)(\s|,)/g) { if ($1 eq 'client') { $rec{$id}->{'month'} = sprintf "%s", $month; $rec{$id}->{'day'} = sprintf "%d", $day; $rec{$id}->{'time'} = sprintf "%s", $time; } $rec{$id}->{$1} = $2; } } } } close(MAIL); foreach my $id (sort { $rec{$a}->{'time'} cmp $rec{$b}->{'time'} } keys %rec) { $rec{$id}->{'client'} =~ s/(.+)\[(\d+\.\d+\.\d+\.\d+)\]/$2/; $rec{$id}->{'from'} =~ s/<(.+)>/$1/; $rec{$id}->{'to'} =~ s/<(.+)>/$1/; if ( $rec{$id}->{'removed'} && $rec{$id}->{'client'} ne '127.0.0.1' ) { if ($rec{$id}->{'from'} ne 'root@domen.com') { $sth->execute($rec{$id}->{'month'},$rec{$id}->{'day'},$rec{$id}->{'time'},$rec{$id}->{'client'},$rec{$id}->{'from'},$rec{$id}->{'to'},$rec{$id}->{'size'}); } } } $sth->finish; $dbh->disconnect; Вот собственно и вся программа. Принцип обработки такой: 1) Открывается журнальный файл maillog, находящийся в каталоге /var/log/; 2) В скалярную переменную $line последовательно в цикле помещается каждая строка журнала; 3) С помощью функции split строка дробится на составляющие элементы; 4) Выделение нужной информации основано на поиске Message-ID, который уникален для каждого обрабатываемого письма; 5) Попутно исключается учет писем, обрабатываемых различными фильтрами (не ведется учет писем, проходящих через localhost); 6) Также исключается учет писем от различных служб на ящик root@domen.com. Программу легко переписать для собственных нужд, если Вам потребуется дополнительная информация о письмах. После того, как скрипт написан, необходимо в Cron внести запуск этого скрипта за несколько минут до полуночи (т.е. до ротации). Выполняем crontab -e, вносим следующую строчку: 58 23 * * * /root/Scripts/maillog.pl Теперь все. Удачи и спокойной работы!

<< Предыдущая ИНДЕКС Правка src / Печать Следующая >>

Обсуждение [ Линейный режим | Показать все | RSS ]
 
  • 1.1, Skif, 17:50, 04/05/2006 [ответить] [смотреть все]
  • +/
    Так, мелкие замечания:
    month varchar(10), day char(2) -почему не заменить на тип date имхо, разумнее, тем более парсинг не займет много времени %hash даст спасенье. Да и процес сравнения для MySQL пойдет легче и быстрее.
    При мелкой нагрузке - тоесть редких выборках - такая база нормально дышать будет. При большой - активное составление отчетов и прочая... Касательно ключей - даже не знаю что сказать. Скорее разумнее сделать индексацию по rcpt_to и mail_from + size писем, введя в качестве primary key что-то типа id поля, с auto encrement. Почему так? Потому что ключами(индексами) надо делать поля по которым выбираются данные, а не те которые выбираются. Если педположить, что интересует конкретно время прохождения письма от pupkin@domen к vasia@domen2, тогда это разумно...Но здесь претензии скользки по определению - надо решать на этапе проектирование БД, что с ней делать будут.
    А так в принципе, ничего...
     
  • 1.2, Vershinin Egor, 18:37, 04/05/2006 [ответить] [смотреть все]
  • +/
    Большое спасибо за замечания - учту в будущем!
    Честно говоря это мой первый опыт самостоятельной работы с Perl-ом и MySQL-ем, к чему весьма способствовала Ваша статья:
    http://www.opennet.ru/base/net/ng_billing_letter.txt.html
     
  • 1.3, Algor, 07:10, 05/05/2006 [ответить] [смотреть все]
  • +/
    Чтобы опыту набраться, можно и такие скрипты писать, для реальных же задач даже незнаю.
    У меня на релее около 50к писем в день и около 2к пользователей которые эти письма пишут, но задачи возникают как правило:
    1.) посмотреть доставилось ли письмо от одного пользователя к другому (в основном за сегодняшний день, и раза три было посмотреть за неделю)
    2.) какие письма были от такого то пользователя и кому
    3.) сколько спама и вирусов отсеилось
    4.) какой общий объем почты ушел и пришел.

    1,2,3 решаются с помощью простых sh скриптов (4 строчки скрипт), время выполнения которых до 10 сек
    3,4 решаются с помощью pflogsumm

     
  • 1.4, Сергей, 07:33, 05/05/2006 [ответить] [смотреть все]
  • +/
    Согласен с Algor

    Когда логи сервака занимают по 300-400 метров в день, особо с БД не поработаешь. Plain-text парсить гораздо эффективнее с точки зрения использования ресурсов системы.

    Я даже не представляю, сколько perl отожрет памяти, если ему скормить достаточно большой лог.

     
  • 1.5, Vershinin Egor, 08:06, 05/05/2006 [ответить] [смотреть все]
  • +/
    А может Вы проверите эту программу на своих логах и сообщите результат?

    У меня такого трафика нет, к сожалению :)

     
  • 1.6, Vershinin Egor, 08:11, 05/05/2006 [ответить] [смотреть все]  
  • +/
    Я тестировал эту программу на логах в 2 Мб и 25 Мб. Без записи в БД, со сбросом информации в файл:
    ./maillogs > mail.txt эта программа отрабатывала лог за 2 секунды (увеличение размера лога в 10 раз на скорости не сказалось).

    Был бы очень признателен, если ы кто-нибудь протестировал прогу на больших журналах.

     
  • 1.7, Сергей, 08:31, 05/05/2006 [ответить] [смотреть все]  
  • +/
    to Vershinin Egor

    Прогоню попробую...
    Но смысла в этом нет. Для больших логов гораздо нужнее утилиты выбора конкретной информации (поиск следов конкретного письма).
    Кстати, сколько занимает база для лога в 25 мегабайт?

     
  • 1.8, Vershinin Egor, 08:34, 05/05/2006 [ответить] [смотреть все]  
  • +/
    Примерно 450 кб
     
  • 1.9, Kuzmich, 08:49, 05/05/2006 [ответить] [смотреть все]  
  • +/
    1. Интересно как поведет себя скрипт, если в конец файла /var/log/maillog будут дописываться данные, и смогут ли они туда вобще дописываться при открытом файле.
    2. Выполнение скрипта лучше поставить в logrotate, а не в cron, и после того как журнал ротэйтнулся, тогда первый вопрос отпадает сразу.
     
  • 1.10, Сергей, 08:56, 05/05/2006 [ответить] [смотреть все]  
  • +/
    to Vershinin Egor

    ниче он у меня в логах не обнаружил:
    21.03.2006 23:59:59 KRAT xxx.xxx.xxx [info] postfix/qmgr[11146]: [ID 197553 local1.info] 814DB24912: removed

    пробежался по файлу и все

    это все из-за split на самом деле, формат логов может разниться, поэтому нехорошо привязываться к своему логу

     
  • 1.11, Сергей, 10:52, 05/05/2006 [ответить] [смотреть все]  
  • +/
    прогнал я скрипт с большим логом 310Mб памяти сожрал во время выполнения 128Мб... весь текст скрыт [показать]
     
     
  • 2.12, Skif, 13:33, 05/05/2006 [^] [ответить] [смотреть все] [показать ветку]  
  • +/
    Ну зачем же так человека расстраивать Все же вектор напрвлености нужно зада... весь текст скрыт [показать] [показать ветку]
     
     
  • 3.13, Skif, 13:43, 05/05/2006 [^] [ответить] [смотреть все]  
  • +/
    Извини, не Женя, а Егор. :)
     
  • 3.14, Сергей, 14:03, 05/05/2006 [^] [ответить] [смотреть все]  
  • +/
    Всеми руками-ногами присоединяюсь Конечно, почти так Точнее, интересующую меня... весь текст скрыт [показать]
     
  • 1.15, Жириновский, 20:46, 07/09/2008 [ответить] [смотреть все]  
  • +/
    Здравствуйте товарищи!

    а как можно брать каждные 2 минуты и вставлять их в таблицу?

    пример:
    1) открывайт файло логов
    2) блокируем файл для записи других прграмм
    3) переносим в СУБД
    4) очищаем файл
    5) разблориуем файл

    такая схема реализации подойдет?

     
  • 1.16, Жириновский, 20:48, 07/09/2008 [ответить] [смотреть все]  
  • +/
    или нужно синхронизировать с помощью XML ?

    или еще как-то можно?

     
  • 1.17, Жириновский, 16:26, 08/09/2008 [ответить] [смотреть все]  
  • +/
    синхронизировасть с помощю дампа с Storable наверное надо...
     
  • 1.18, Watcher, 08:44, 13/01/2009 [ответить] [смотреть все]  
  • +/
    Я у себя сдела primary key
    month  
    day  
    time  
    mailfrom  
    rcptto,
    а то иначе теряются записи,(при вставке указывает на дублирующие записи), так как за секунду может быть несколько писем., Также в таблицу не вносятся записи, если письмо посылалось копией кому-либо еще.
     
  • 1.19, Avolon, 13:01, 21/01/2009 [ответить] [смотреть все]  
  • +/
    при обработке выдает
    DBD::mysql::st execute failed: Column 'month' cannot be null at ./log.pl line 55.
    Что делать то???
     
  • 1.20, Серга, 20:42, 20/04/2010 [ответить] [смотреть все]  
  • +/
    to Avolon:
    попробуй убери $rec{$id}->{'client'} ne '127.0.0.1'
    вместо етого ип пропиши како-то левый...
     
  • 1.21, Серга, 19:00, 19/05/2010 [ответить] [смотреть все]  
  • +/
    подскажите как етот скрипт изменить, что бы можно было и статус письма из логов получить?
     
  • 1.22, Scales, 12:24, 20/05/2010 [ответить] [смотреть все]  
  • +/
    mail.log примерно 415 метров
    отработал приблизительно за минуты 3
    Спасибо!
     
  • 1.23, Евгений, 14:21, 27/10/2015 [ответить] [смотреть все]  
  • +/
    как добавить год? нужно чтобы в базу писался в отдельную колонку год. Никак не могу разобраться.
     

    Ваш комментарий
    Имя:         
    E-Mail:      
    Заголовок:
    Текст:





      Закладки на сайте
      Проследить за страницей
    Created 1996-2017 by Maxim Chirkov  
    ДобавитьРекламаВебмастеруГИД  
    Hosting by Ihor