segunda-feira, 21 de março de 2016

Coletando Estatísticas de E-mail do Postfix com Shell Script, Pflogsumm e Zabbix

Introdução

 Em muitas situações precisamos coletar indicadores, entre eles quantitativos de e-mails, nesse post demonstro como coletar esses dados de um servidor Postfix, tratá-los e enviá-los ao Zabbix.
Para melhor entendimento das filas e até alternativas de coleta, recomendo a leitura desse post do grande Guto Carvalho.

O responsável por gerar as estatísticas é o script em Perl pflogsumm.

Dependências

A única dependência do pflogsumm é o módulo Perl Date-Calc.
# yum install perl-Date-Calc

Download

Realizar o download do script
# wget http://jimsun.linxnet.com/downloads/pflogsumm-1.1.3.tar.gz

Descompactar o script
# tar -xzvf pflogsumm-1.1.3.tar.gz

Copiar o script para o diretório de binários
# cp pflogsumm-1.1.3/pflogsumm.pl /usr/local/bin/

Gerar 1ª remessa

Vamos gerar um primeiro arquivo contendo as estatísticas com base nos arquivos de log.
# pflogsumm.pl /var/log/maillog* > emails.txt

Separar o bloco de dados que me interessa

A linha 59 contém as informações da última data que me interessa (Mar  8 2016) e descontando 32 linhas eu chego na linha com a primeira data que me interessa (Feb  7 2016). Você deve adaptar os valores para a sua necessidade.
# head -59 emails.txt | tail -32
    Feb  7 2016        19         33         81          0          2
    Feb  8 2016        19         26
    Feb  9 2016        31         49
    Feb 10 2016        58         83          1
    Feb 11 2016       353       9975       1284        121
    Feb 12 2016      1321      21503      24157       5264
    Feb 13 2016        22        124       8878          0          1
    Feb 14 2016        18        129       6135
    Feb 15 2016       153       3839        216         49
    Feb 16 2016       279       7208       1048         75          1
    Feb 17 2016       101       2536        272         33          1
    Feb 18 2016       450      12107       1535        143
    Feb 19 2016       950      13594       5547       5176
    Feb 20 2016        17         36       5855          1          3
    Feb 21 2016        25         89       3445          1
    Feb 22 2016       215       5385        443        127
    Feb 23 2016        99       2176         83         23
    Feb 24 2016       562       8202       3850       2337
    Feb 25 2016       220       8551       3512        102
    Feb 26 2016       975      15136       6450       5462
    Feb 27 2016        23         39       5766          0          8
    Feb 28 2016        22         99       4082          0          2
    Feb 29 2016       462      12157        482        157
    Mar  1 2016       539       9674       1131        193
    Mar  2 2016       143       4899        975         57
    Mar  3 2016        20         98        422          0         11
    Mar  4 2016       978      16457       6621       5071          1
    Mar  5 2016        21         40       5977         14
    Mar  6 2016        22         88       4331          0          1
    Mar  7 2016       384      11030        446        196         10
    Mar  8 2016       266       8579        431        102

Converter as datas para o formato Unix Timestamp

O Zabbix possui um utilitário (zabbix_sender) que permite o envio em lote de informações, mas para isso as datas precisam estar no formato Unix Timestamp ou Epoch.

Para isso eu usei o site Epoch Unix Time Stamp Converter para converter as datas. Sim eu sei que poderia usar o comando date +%s, mas eram poucos dados e eu fiz por lá ;-). Abaixo o txt que eu montei com correlação de datas (datas2.txt) separando a data normal da convertida por um <tab>.
Feb 7 2016    1454832000
Feb 8 2016    1454918400
Feb 9 2016    1455004800
Feb 10 2016    1455091200
Feb 11 2016    1455177600
Feb 12 2016    1455264000
Feb 13 2016    1455350400
Feb 14 2016    1455436800
Feb 15 2016    1455523200
Feb 16 2016    1455609600
Feb 17 2016    1455696000
Feb 18 2016    1455782400
Feb 19 2016    1455868800
Feb 20 2016    1455955200
Feb 21 2016    1456041600
Feb 22 2016    1456128000
Feb 23 2016    1456214400
Feb 24 2016    1456300800
Feb 25 2016    1456300800
Feb 26 2016    1456473600
Feb 27 2016    1456560000
Feb 28 2016    1456646400
Feb 29 2016    1456732800
Mar 1 2016    1456819200
Mar 2 2016    1456905600
Mar 3 2016    1456992000
Mar 4 2016    1457078400
Mar 5 2016    1457164800
Mar 6 2016    1457251200
Mar 7 2016    1457337600
Mar 8 2016    1457424000

Gerar os arquivos com datas e valores

Em seguida vou separar apenas a data no formato Unix Timestamp
# cat datas2.txt | tr '\t' ' ' | tr -s ' ' | cut -d ' ' -f4 > datas.txt

E agora vou gerar um arquivo para cada dado que vou coletar (received, delivered, deferred, bounced, rejected e total). A linha 58 contém a última informação que nos interessa e a linha 32 a primeira informação.
# head -58 emails.txt | tail -32 | tr -s ' ' | cut -d ' ' -f5 > received.txt
# head -58 emails.txt | tail -32 | tr -s ' ' | cut -d ' ' -f6 > delivered.txt
# head -58 emails.txt | tail -32 | tr -s ' ' | cut -d ' ' -f7 > deferred.txt
# head -58 emails.txt | tail -32 | tr -s ' ' | cut -d ' ' -f8 > bounced.txt
# head -58 emails.txt | tail -32 | tr -s ' ' | cut -d ' ' -f9 > rejected.txt


O total é um pouco mais complicado, pois temos linhas vazias, então vamos primeiro gerar o arquivo:
# paste received.txt delivered.txt deferred.txt bounced.txt rejected.txt | tr '\t' '+' | grep '+$' > total.txt

Mas como podemos observar, teremos problemas se enviarmos esses valores para a calculadora (bc)
# cat total.txt
++++
19+26+++
31+49+++
58+83+1++
353+9975+1284+121+
1321+21503+24157+5264+
18+129+6135++
153+3839+216+49+
450+12107+1535+143+
950+13594+5547+5176+
25+89+3445+1+
215+5385+443+127+
99+2176+83+23+
562+8202+3850+2337+
220+8551+3512+102+
975+15136+6450+5462+
462+12157+482+157+
539+9674+1131+193+
143+4899+975+57+
21+40+5977+14+
266+8579+431+102+


Para resolver o problema precisamos eliminar todos os sinais de “+” que estejam no final da linha, como pode ser observado, por exemplo, nas 5 primeiras linhas.
# sed -i 's/[+]*$//' total.txt

Agora o arquivo está pronto para ser enviado para a calculadora e, nos retornar o total.
# cat total.txt
19+26
31+49
58+83+1
353+9975+1284+121
1321+21503+24157+5264
18+129+6135
153+3839+216+49
450+12107+1535+143
950+13594+5547+5176
25+89+3445+1
215+5385+443+127
99+2176+83+23
562+8202+3850+2337
220+8551+3512+102
975+15136+6450+5462
462+12157+482+157
539+9674+1131+193
143+4899+975+57
21+40+5977+14
266+8579+431+102

A quantidade de linhas do arquivo, será necessário para o próximo passo, mas como usamos o comando tail -32, já sabemos que o arquivo tem 32 linhas ;-)

Automatizar a geração do arquivo que será usado para alimentar o Zabbix

Nada melhor que um Shell Script para automatizar as tarefas repetitivas do dia-a-dia. Troque o nome "Server" pelo nome do Host cadastrado no Zabbix
# vi gera_zabbix.sh

#!/bin/bash

# RECEIVED
for ((i=1; i<=32; i++))
do
        data=`head -$i datas.txt | tail -1`
        valor=`head -$i received.txt | tail -1`
        echo "Server mails.received $data $valor" >> valores_zabbix.txt
done

# DELIVERED
for ((i=1; i<=32; i++))
do
        data=`head -$i datas.txt | tail -1`
        valor=`head -$i delivered.txt | tail -1`
        echo "Server mails.delivered $data $valor" >> valores_zabbix.txt
done

# DEFERRED
for ((i=1; i<=32; i++))
do
        data=`head -$i datas.txt | tail -1`
        valor=`head -$i deferred.txt | tail -1`
        echo "Server mails.deferred $data $valor" >> valores_zabbix.txt
done

# BOUNCED
for ((i=1; i<=32; i++))
do
        data=`head -$i datas.txt | tail -1`
        valor=`head -$i bounced.txt | tail -1`
        echo "Server mails.bounced $data $valor" >> valores_zabbix.txt
done

# REJECTED
for ((i=1; i<=32; i++))
do
        data=`head -$i datas.txt | tail -1`
        valor=`head -$i rejected.txt | tail -1`
        echo "Server mails.rejected $data $valor" >> valores_zabbix.txt
done

# TOTAL
for ((i=1; i<=32; i++))
do
        data=`head -$i datas.txt | tail -1`
        valor=`head -$i total.txt | tail -1 | bc`
        echo "Server mails.total $data $valor" >> valores_zabbix.txt
done


Gerar o arquivo que vai alimentar o Zabbix
# sh gera_zabbix.sh

Como alguns valores estavam em branco, o arquivo ficou com algumas falhas, como essa
# cat valores_zabbix.txt
Server mails.received 1454832000
Server mails.received 1454918400 19


Vamos substituir esses espaços em banco, como na primeira linha, por 0 para que o Zabbix possa receber um valor para cada um os campos
# sed -i 's/00 $/00 0/g' valores_zabbix.txt

E agora o arquivo está correto
# cat valores_zabbix.txt
Server mails.received 1454832000 0
Server mails.received 1454918400 19

Criar os itens no Zabbix

Para que o Zabbix possa receber os dados, é preciso que sejam criados itens com as mesmas chaves que constam no arquivo. E o tipo do item deve ser Zabbix trapper.
Item E-mails Atrasados

Template Estatistica E-mail Postfix

Se você não quiser perder tempo criando os itens, eu disponibilizei o template aqui. Esse template contem os 6 itens que vamos precisar e um gráfico com todos os itens.

Populando o Zabbix com os dados

# zabbix_sender -z Proxy -T -i valores_zabbix.txt
info from server: "processed: 192; failed: 0; total: 192; seconds spent: 0.001544"
sent: 192; skipped: 0; total: 192

Coletando os valores diários

O pflogsumm.pl possui o parametro "-d yesterday" que gera as informações do dia anterior, então minha estratégia será a de todos os dias às 08:00 popular o Zabbix com os dados consolidados do dia anterior.

Esse parametro permite utilizar os totais do dia ou os valores de hora em hora, eu vou utilizar os valores totais, mas nada te impede de adaptar o script para coletar os valores por hora.

# /usr/local/bin/pflogsumm.pl -d yesterday /var/log/maillog* | more
Postfix log summaries for Mar  9

Grand Totals
------------
messages

     79   received
   1648   delivered
      0   forwarded
     11   deferred  (188  deferrals)
     34   bounced
     10   rejected (0%)
      0   reject warnings
      0   held
      0   discarded (0%)

   2790k  bytes received
  29781k  bytes delivered
     18   senders
      5   sending hosts/domains
   1514   recipients
     73   recipient hosts/domains


Per-Hour Traffic Summary
------------------------
    time          received  delivered   deferred    bounced     rejected
    --------------------------------------------------------------------
    0000-0100           0          0         16          0          0
    0100-0200           0          0         16          0          0
    0200-0300           0          0         12          0          0
    0300-0400           0          0         14          0          0

Automatizando o envio diário de informações

Primeiro vamos criar um diretório para armazenar nossos scripts
# mkdir /Scripts_Servicos

Vamos criar o script que coleta as estatísticas e  envia automaticamente para o Zabbix
# vi /Scripts_Servicos/estatisticas_email.sh

#!/bin/bash
 
# Todos dos dias gera um novo arquivo
/usr/local/bin/pflogsumm.pl -d yesterday /var/log/maillog* > /Scripts_Servicos/yesterday

# Separa as informacoes que nos interessam
received=`head -12 /Scripts_Servicos/yesterday | grep received | tr -s " " | cut -d " " -f2`
delivered=`head -12 /Scripts_Servicos/yesterday | grep delivered | tr -s " " | cut -d " " -f2`
deferred=`head -12 /Scripts_Servicos/yesterday | grep deferred | tr -s " " | cut -d " " -f2`
bounced=`head -12 /Scripts_Servicos/yesterday | grep bounced | tr -s " " | cut -d " " -f2`
rejected=`head -12 /Scripts_Servicos/yesterday | grep rejected | tr -s " " | cut -d " " -f2`
total=`echo $received+$delivered+$deferred+$bounced+$rejected | bc`
data=`date --date yesterday +%s`

# Apaga o arquivo do dia anterior
rm -rf /Scripts_Servicos/valores_zabbix

# Monta o arquivo
echo "Server mails.received $data $received" >> /Scripts_Servicos/valores_zabbix
echo "Server mails.delivered $data $delivered" >> /Scripts_Servicos/valores_zabbix
echo "Server mails.deferred $data $deferred" >> /Scripts_Servicos/valores_zabbix
echo "Server mails.bounced $data $bounced" >> /Scripts_Servicos/valores_zabbix
echo "Server mails.rejected $data $rejected" >> /Scripts_Servicos/valores_zabbix
echo "Server mails.total $data $total" >> /Scripts_Servicos/valores_zabbix

# Envia os dados para o Zabbix
zabbix_sender -z Proxy -T -i /Scripts_Servicos/valores_zabbix


Tornar o script executável
# chmod +x /Scripts_Servicos/estatisticas_email.sh

Agendar a execução do Script
# crontab -e

# Todos os dias as 08:00 envia os dados estatisticos de e-mail para o Zabbix
00      08      *       *       *       /Scripts_Servicos/estatisticas_email.sh

Referências

Guto Carvalho
Epoch Unix Time Stamp Converter
Pflogsumm
Zabbix Sender