| Revision 7 (by dpavlin, 2002/06/11 15:17:28) |
parse maillog from different machines and report it in message-by-message
form
|
#!/usr/bin/perl -w
# 2002-06-11 Dobrica Pavlinusic <dpavlin@rot13.org>
#
# Unroll sendmail and/or postfix log on message-by-message basis
#
# Usage:
# $ cat */mail.log | ./flow_mail.pl | vi -R -
#
$|=1; # flush stdout
my $debug = 0;
my $nr=0;
my %id2nr_hash;
my %nr2id_hash;
my %nr_line;
my %id_line;
my @t = ('','',0); # placeholder for time stamp
print STDERR "reading log from stdin...\n 0---------12---------24";
sub fix_id {
if (my $id=$_[0]) {
# $id =~ tr/a-zA-Z0-9/_/cs;
$id =~ s/:$//;
return $id;
}
}
sub id2nr {
# "clever" way to find message number -- try current one,
# if that fails use first one...
my $id = $_[0];
if (grep(/$nr/,@{$id2nr_hash{$id}})) {
return $nr;
} else {
return $id2nr_hash{$id}[0];
}
}
sub push_id2nr {
my ($id,$nr) = @_;
if (! grep(/$nr/,@{$id2nr_hash{$id}})) {
push @{$id2nr_hash{$id}}, $nr;
}
}
sub push_nr2id {
my ($nr,$id) = @_;
if (! grep(/\Q$id\E/,@{$nr2id_hash{$nr}})) {
push @{$nr2id_hash{$nr}}, $id;
}
}
while(<>) {
chomp;
chomp;
my $line = $_;
my @arr=split(/\s+/,$line);
if ($arr[5] && $arr[5] =~ m/^[a-zA-Z0-9]*:$/) {
my $id = fix_id($arr[5]);
print STDERR "id: $id\n" if ($debug);
if (! defined id2nr($id)) {
$nr++;
print STDERR "new: $nr -- $id\n" if ($debug);
push_id2nr($id,$nr);
push_nr2id($nr,$id);
push @{$nr_line{$nr}}, $line;
push @{$id_line{$id}}, $line;
} else {
my $c_nr=id2nr($id);
print STDERR "line: $c_nr -- $id\n" if ($debug);
if ($arr[9] && $arr[12] && $arr[9] eq "status=sent") {
# postfix follow
my $f_id=fix_id($arr[12]);
push_id2nr($f_id,$c_nr);
push_nr2id($c_nr,$f_id);
print STDERR "follow postfix: $c_nr -> $f_id -- ",join("|",@arr),"\n" if ($debug);
} elsif ($arr[15] && $arr[15] eq "stat=Sent") {
# sendmail follow
if (my $f_id=fix_id($arr[19])) {
push_id2nr($f_id,$c_nr);
push_nr2id($c_nr,$f_id);
print STDERR "follow sendmail: $c_nr -> $f_id -- ",join("|",@arr),"\n" if ($debug);
}
}
push @{$nr_line{$c_nr}}, $line;
push @{$id_line{$id}}, $line;
}
} else {
# this is a cludge. If you don't have much other
# log entries excpt mailers your progress indicator won't
# be updated often enough. Since I do, I save a lot
# of computing this way :-)
my $h = $arr[2] || ''; $h =~ s/:.*//g;
if ($t[0] ne $arr[0] || $t[1] != $arr[1]) {
printf STDERR "\n%3s %2d ",$arr[0],$arr[1];
@t = ($arr[0], $arr[1], 0);
}
if ($h != $t[2]) {
print STDERR "." x ($h - $t[2]);
$t[2] = $h;
}
}
}
print STDERR "\nprocessed $nr messages\n";
print STDERR "saving...\n0","-"x21,"50%","-"x21,"100%\n.";
my $last_pcnt=0;
for ($i = 1; $i < $nr; $i++) {
print "-" x 60,"\n";
if ($nr2id_hash{$i}) {
print "nr: $i id: ",join(", ",@{$nr2id_hash{$i}}),"\n";
# foreach (@{$nr_line{$i}}) {
# print "$_\n";
# }
foreach $id (@{$nr2id_hash{$i}}) {
foreach (@{$id_line{$id}}) {
print "$_\n";
}
}
}
my $pcnt = int($i*50/$nr);
if ($pcnt > $last_pcnt) {
print STDERR ".";
$last_pcnt = $pcnt;
}
}
print STDERR "\nover...\n";