Cкрипт
findmail2.pl и findmail2.sh разработан для подсчета писем в лог-файле Postfix.
Основные возможности:
-
findmail2.sh - bash версия,
findmail2.pl - perl версия;
-
Принудительный выбор лог-файла (если не указан, то по умолчанию /var/log/mail);
-
Поиск по дате и e-mail адресу отправителя и получателя;
-
Фильтр по статусу и по релею.
mail:/home/postadmin # findmail2.pl -l /var/log/mail-20091124.gz -f user@mydomain.com -s K -d "Nov 23 13"
Subject: "findmail2.sh -l /var/log/mail-20091124.gz -f user@mydomain.com -s M -d Nov 23 13"
Поиск писем от user@mydomain.com в /var/log/mail-20091124.gz с фильтром по времени: "Nov ?23 13"
Фильтрация лога. Это может занять некоторое время... Готово
Для id=1323AF8F78:
dsn=2.0.0, status=sent, Nov 23 13:26:25, to=<polina@octet.com>, size=28.78 KBytes
Всего найдено писем с id=1323AF8F78: 1 Полный размер: 28.78 KBytes
Для id=2E16B58AC41:
dsn=2.6.0, status=sent, Nov 23 13:35:46, to=<polina@octet.com>, size=1.65 KBytes
dsn=4.1.0, status=deferred, Nov 23 13:25:55, to=<polina@octet.com>, size=1.65 KBytes
Всего найдено писем с id=2E16B58AC41: 2 Полный размер: 3.30 KBytes
Для id=50004F8F78:
dsn=2.0.0, status=sent, Nov 23 13:25:55, to=<dvina@esst.com>, size=1.63 KBytes
Всего найдено писем с id=50004F8F78: 1 Полный размер: 1.63 KBytes
Для id=85282190C81:
dsn=2.6.0, status=sent, Nov 23 13:35:46, to=<lena@su.net>, size=28.79 KBytes
dsn=4.1.0, status=deferred, Nov 23 13:26:25, to=<lena@su.net>, size=28.79 KBytes
Всего найдено писем с id=85282190C81: 2 Полный размер: 57.58 KBytes
Всего найдено уникальных id: 4 Полный размер: 91.29 KBytes Затрачено времени(сек): 1
mail:/home/postadmin #
Пример cкрипта findmail2.pl и findmail2.sh для подсчета писем по лог-файлам Postfix
(Скачать файл можно будет
здесь. ЗЫ Не тыкать! Жать правой кнопкой: сохранить ссылку как...)
Условия:
Используй:
findmail2.pl -f|-t e-mail [-r relay] [-l logfile] [-s K|M|G] [-d "Mmm[ D[ HH[:MM[:SS]]]]"] [-S state] -h
- -l логфайл;
- -f|-t e-mail отправителя|получателя;
- -r релей (по умолчанию все);
- -s единица измерения размера (по умолчанию байт);
- -d ограничить датой (например "Nov 2 12:00:00");
- -S статус (например sent);
- -h вывод справки.
Обязательные параметры: e-mail отправителя или получателя.
Необязательные параметры:релей (например 127.0.0.1), дата в формате используемом в лог-файле (например "Mar 10 12:00:00" или "Mar 10 12" и т.д. обязательно в кавычках), логфайл, единица измерения и статус.
Пример:
findmail2.pl -l /var/log/mail-20091124.gz -f user@mydomain.com -s K -d "Nov 23 13"
Текст findmail2.pl:
#!/usr/bin/perl -w
#
#Copyright 2010 Konstantin Nadezhdin <w.homenki.ru>
#
#This program is free software: you can redistribute it and/or modify
#it under the terms of the GNU General Public License as published by
#the Free Software Foundation, either version 3 of the License, or
#(at your option) any later version.
#
#This program is distributed in the hope that it will be useful,
#but WITHOUT ANY WARRANTY; without even the implied warranty of
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
#GNU General Public License for more details.
#
#You should have received a copy of the GNU General Public License
#along with this program. If not, see <http://www.gnu.org/licenses/>.
#
use strict;
my($nexts,$fl,$fltype,$fs,$fd,$fS,$fe,$fr) = ("","/var/log/mail","","B","","","","");
my($GREP_BIN) = "/usr/bin/grep";
my(%ftf_str) = ("t","для","f","от");
my($size,$su) = ("Bytes",1);
my($SIZESALL,$count,$SIZE,$mailcount,$SIZESN,$worktime,$starttime) = 0;
my(%ID_SIZE,%ID_FTE,%ID_LOG,%ID_COUNT);
my($FILTERED_ID,$Fld,$ftf,$ID) = "";
foreach (@ARGV) {
if ($_ eq "-l") {
$nexts = "fl";
} elsif ($_ eq "-f") {
$nexts = "ff";
} elsif ($_ eq "-t") {
$nexts = "ft";
} elsif ($_ eq "-r") {
$nexts = "fr";
} elsif ($_ eq "-s") {
$nexts = "fs";
} elsif ($_ eq "-d") {
$nexts = "fd";
} elsif ($_ eq "-S") {
$nexts = "fS";
} elsif ($_ eq "-h") {
die "Используй -f|-t e-mail [-r relay] [-l logfile] [-s K|M|G] [-d \"Mmm[ D[ HH[:MM[:SS]]]]\"] [-S state] -h
\t-l логфайл;
\t-f|-t e-mail отправителя|получателя;
\t-r релей (по умолчанию все);
\t-s единица измерения размера (по умолчанию байт);
\t-d ограничить датой (например \"Nov 2 12:00:00\");
\t-S статус (например sent);
\t-h вывод справки.\n";
} else {
if ($nexts eq "fl") {
$fl = $_;
} elsif ($nexts eq "ff") {
$fe = $_; $ftf = "f";
} elsif ($nexts eq "ft") {
$fe = $_; $ftf = "t";
} elsif ($nexts eq "fr") {
$fr = $_;
} elsif ($nexts eq "fs") {
$fs = $_;
} elsif ($nexts eq "fd") {
($fd = $_) =~ s/ / \?/;
} elsif ($nexts eq "fS") {
$fS = $_;
}
$nexts = "";
}
}
print "Subject: \" @ARGV\"\n";
if ($fl eq "") {
print "Не указан лог, использую по умолчанию!\n";
$fl = "/var/log/mail";
}
(-e $fl) || die "Ошибка, $fl не существует\n";
($fe eq "") && die "Не указан e-mail отправителя или получателя\n";
print "Поиск писем $ftf_str{$ftf} $fe в $fl";
($fd eq "") || print " с фильтром по времени: \"$fd\"";
($fS eq "") || print " с фильтром по статусу: \"$fS\"";
print "\n";
($fltype = $fl) =~ s/^.*\.//;
if ($fltype eq "gz") {
$GREP_BIN="/usr/bin/zgrep";
} elsif ($fltype eq "bz2") {
$GREP_BIN="/usr/bin/bzgrep";
}
if ($fs eq "K") {
$su = 1024; $size = "K" . $size;
} elsif ($fs eq "M") {
$su = 1048576; $size = "M" . $size;
} elsif ($fs eq "G") {
$su = 1073741824; $size = "G" . $size;
}
print "Фильтрация лога. Это может занять некоторое время... ";
$starttime = `date +%s.%N`;
if ($ftf eq "t") {
open(LOG,"$GREP_BIN -Ei \"^$fd.*: to=<$fe>, relay=$fr.*status=$fS\" $fl|") || die "Ошибка $!\n";
while (<LOG>) {
chomp;
($Fld = (split(/ ?/))[5]) =~ s/[:,]//g;
$ID_LOG{$Fld} .= join(" ",(split(/ ?/))[7,10,11]) . ", " . join(" ",(split(/ ?/))[0,1,2,]) . "\n";
$FILTERED_ID .= "$Fld|" unless (defined($ID_COUNT{$Fld}));
$ID_COUNT{$Fld}++;
}
} elsif ($ftf eq "f") {
open(LOG,"$GREP_BIN -Ei \"^$fd.*: from=<$fe>\" $fl|") || die "Ошибка $!\n";
while (<LOG>) {
chomp;
($Fld = (split(/ ?/))[5]) =~ s/[:,]//g;
($ID_SIZE{$Fld} = (split(/ ?/))[7]) =~ s/(^size=|[:,]$)//g unless (defined($ID_SIZE{$Fld}));
$FILTERED_ID .= "$Fld|" unless (defined($ID_COUNT{$Fld}));
$ID_COUNT{$Fld}++;
}
}
close(LOG);
if ($FILTERED_ID eq "") { print "Ничего не найдено.\n"; die "$!\n"; }
chop($FILTERED_ID);
if ($ftf eq "t") {
open(LOG,"$GREP_BIN -Ei \"^$fd.*($FILTERED_ID): from=\" $fl|") || die "Ошибка $!\n";
while (<LOG>) {
chomp;
($Fld = (split(/ ?/))[5]) =~ s/[:,]//g;
if (defined($ID_COUNT{$Fld})) {
$ID_FTE{$Fld} = (split(/ ?/))[6] unless (defined($ID_FTE{$Fld}));
($ID_SIZE{$Fld} = (split(/ ?/))[7]) =~ s/(^size=|[:,]$)//g unless (defined($ID_SIZE{$Fld}));
}
}
} elsif ($ftf eq "f") {
open(LOG,"$GREP_BIN -Ei \"^$fd.*($FILTERED_ID): to=<.*>, relay=$fr.*status=$fS\" $fl|") || die "Ошибка $!\n";
while (<LOG>) {
chomp;
($Fld = (split(/ ?/))[5]) =~ s/[:,]//g;
if (defined($ID_COUNT{$Fld})) {
$ID_LOG{$Fld} .= join(" ",(split(/ ?/))[7,10,11]) . ", " . join(" ",(split(/ ?/))[0,1,2]) . ", " . (split(/ ?/))[6] ."\n";
}
}
}
close(LOG);
print "Готово\n";
foreach $ID (keys(%ID_COUNT)) {
(defined($ID_LOG{$ID})) || next;
$SIZE = $ID_SIZE{$ID} / $su;
$mailcount = $ID_COUNT{$ID};
$SIZESN = $SIZE * $mailcount;
$SIZESALL += $SIZESN;
print "\nДля id=$ID:\n";
foreach (split(/\n/, $ID_LOG{$ID})) {
if ($ftf eq "t") {
printf('%1$s %2$.2f %3$s',"$_, $ID_FTE{$ID} size=" , $SIZE , "$size\n");
} elsif ($ftf eq "f") {
printf('%1$s %2$.2f %3$s',"$_ size=" , $SIZE , "$size\n");
}
}
printf('%1$s %2$.2f %3$s',"Всего найдено писем с id=$ID: $mailcount\tПолный размер:", $SIZESN, "$size\n");
$count++;
}
$worktime = `date -d "-$starttime seconds" "+%s.%N"`;
printf('%1$s %2$.2f %3$s',"\nВсего найдено уникальных id: $count\tПолный размер:", $SIZESALL, "$size\t Затрачено времени(сек): $worktime\n");
Текст findmail2.sh:
#!/bin/bash
#
#Copyright 2010 Konstantin Nadezhdin <w.homenki.ru>
#
#This program is free software: you can redistribute it and/or modify
#it under the terms of the GNU General Public License as published by
#the Free Software Foundation, either version 3 of the License, or
#(at your option) any later version.
#
#This program is distributed in the hope that it will be useful,
#but WITHOUT ANY WARRANTY; without even the implied warranty of
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
#GNU General Public License for more details.
#
#You should have received a copy of the GNU General Public License
#along with this program. If not, see <http://www.gnu.org/licenses/>.
#
nexts=""
fl="/var/log/mail"
fs="B"
fd=""
fS=""
fe=""
fr=""
for i in "$@"; do
case $i in
-l) nexts="fl";;
-f) nexts="ff";;
-t) nexts="ft";;
-r) nexts="fr";;
-s) nexts="fs";;
-d) nexts="fd";;
-S) nexts="fS";;
-h)
echo "Используй $0 -f|-t e-mail [-r relay] [-l logfile] [-s [K|M|G]] [-d Mmm[_D[_HH[:MM[:SS]]]]] [-S state] -h"
echo -e "\t-l логфайл;\n\t-f|-t e-mail отправителя|получателя;\n\t-r релей (по умолчанию все);\n\t-s единица измерения размера (по умолчанию байт);\n\t-d ограничить датой (например Nov_2_12:00:00);\n\t-S статус (например sent);\n\t-h вывод справки."; exit;;
*)
case $nexts in
fl) fl="$i"; nexts="";;
ff) fe="$i"; ftf="f"; nexts="";;
ft) fe="$i"; ftf="t"; nexts="";;
fr) fr="$i"; nexts="";;
fs) fs="$i"; nexts="";;
fd) fd="${i/ / ?}"; nexts="";;
fS) fS="$i"; nexts="";;
esac
;;
esac
done
echo "Subject: \"$0 $*\""
test "$fl" || { echo "Не указан лог, использую по умолчанию!"; fl="/var/log/mail"; }
test -e $fl || { echo "Ошибка, $fl не существует"; exit; }
test "$fe" || { echo "Не указан e-mail отправителя или получателя."; $0 -h; exit; }
case $ftf in
t) ftf_str="для";;
f) ftf_str="от";;
esac
echo "Поиск писем $ftf_str $fe в $fl $(test "$fd" && echo "с фильтром по времени: \"$fd\"") $(test "$fS" && echo "с фильтром по статусу: \"$fS\"")"
fltype="${fl##*.}"
case $fltype in
gz) GREP_BIN="/usr/bin/zgrep";;
bz2) GREP_BIN="/usr/bin/bzgrep";;
*) GREP_BIN="/usr/bin/grep";;
esac
case $fs in
K) su=1024; size="KBytes";;
M) su=1048576; size="MBytes";;
G) su=1073741824; size="GBytes";;
*) su=1; size="Bytes";;
esac
echo -n "Фильтрация лога. Это может занять некоторое время... "
starttime=$(date +%s.%N)
case $ftf in
t)
FILTERED_LOG="$($GREP_BIN -iE "^$fd.*: to=<$fe>, relay=$fr.*status=$fS" $fl)"
FILTERED_ID="$(echo "$FILTERED_LOG" | awk '{print $6}' | sort -u | sed ':a; s/[:,]//g; /$/N; s/\n/|/; ta')"
FILTERED_LOG1="$($GREP_BIN -iE "^$fd.*($FILTERED_ID): from=" $fl)"
ID_SIZE="$(echo "$FILTERED_LOG1" | awk '{print $6";"$8}' | sort -u | sed ':a; s/[:,]//g; /$/N; s/\n/ /; ta')"
;;
f)
ID_SIZE="$($GREP_BIN -iE "^$fd.*: from=<$fe>" $fl | awk '{print $6";"$8}' | sort -u | sed ':a; s/[:,]//g; /$/N; s/\n/ /; ta')"
FILTERED_ID="$(echo "$ID_SIZE" | sed -e 's/;size=[0-9]*//g' -e 's/ /|/g')"
FILTERED_LOG="$($GREP_BIN -E "^$fd.*($FILTERED_ID): to=<.*>, relay=$fr.*status=$fS" $fl)"
;;
esac
echo "Готово"
SIZESALL=0
count=0
for i in $ID_SIZE; do
ID="${i%%;size=*}"
SIZEB="${i##*;size=}"
SIZE="$(echo "scale=2; $SIZEB/$su" | bc -l)"
case $ftf in
t)
fte="$(echo "$FILTERED_LOG1" | awk '/^'$fd'.*'$ID'.*: from=/ {print $7}' | sort --key=1)"
MAILS="$(echo "$FILTERED_LOG" | awk '/^'$fd'.*'$ID'.*: to=<'$fe'>.*status='$fS'/ {print $8" "$11" "$12", "$1" "$2" "$3", '"$fte"' size='"$SIZE $size"'"}' | sort --key=1)"
;;
f)
MAILS="$(echo "$FILTERED_LOG" | awk '/^'$fd'.*'$ID'.*: to=<.*status='$fS'/ {print $8" "$11" "$12", "$1" "$2" "$3", "$7" size='"$SIZE $size"'"}' | sort --key=1)"
;;
esac
mailcount=0
SIZESN="0"
if [ "$MAILS" ]; then
echo -e "\nДля id=$ID:\n$MAILS"
SIZES="$(echo "$MAILS" | sed -e 's/^.*size=//' -e 's/ '$size'$//')"
for j in $SIZES; do SIZESN=$(echo "$SIZESN+$j" | bc -l); let mailcount=$mailcount+1; done
echo -e "Всего найдено писем с id=$ID: $mailcount\tПолный размер: $SIZESN $size"
let count=$count+1
fi
SIZESALL=$(echo "$SIZESALL+$SIZESN" | bc -l)
done
worktime=$(date -d "-$starttime seconds" "+%s.%N")
echo -e "\nВсего найдено уникальных id: $count\tПолный размер: $SIZESALL $size\t Затрачено времени(сек): $worktime"
Что нового в этой версии:
Версия 1.3 (Срд Июн 2 2010):
- Исправлена ошибка разбивки строки в perl версии.
Версия 1.2:
- Переписан на perl.
Версия 1.1:
- Добавлен поиск писем по адресу получателя;
- Добавлен фильтр по релею.
Версия 1.0:
- Первый релиз.