#! /usr/bin/perl # # A parser to glob in smtpserver's log (via 'tail -f', for example) # and to print out those sessions which have errors logged in them. # # # NEW servers make log which has two kinds of session termination # conditions: # #####w \t 221 ... # #####- \t ... # # That is, either a "w"-line with code 221, or a "-"-line. # $match = undef; if (defined($ARGV[0])) { $match = $ARGV[0]; } # # You wonder why this utility was written ? # Well, "technical monitoring with tail -f" is something which probably # is not allowed for people in Telecom Carrier business in Finland, thus # we have to have a way to select only cases containing *errors* (or other # interesting things), while basic flow goes by unseen... # # # We collect streams of inputs of all pids; we discard # such sessions which end happily without presenting # any instance of $haserror. # %pidstore = (); # Key: $pid.".".$sernro %sernrostore = (); # Key: $pid %iserr = (); # key: $pid while () { $line = $_; chomp $line; #print "line='".$line."'\n"; if ($line =~ m/^(.{7}).{4}(.*)$/o) { $pid = $1; $rest = $2; } else { $pid = "**"; $rest = "**"; } #print "pid='".$pid."'\n"; #print "rest='".$rest."'\n"; $isend = 0; if ($rest =~ m/^-/o) { $isend = 1; } if ($rest =~ m/^w\t221/o) { $isend = 1; } $haserror = 0; if (defined ($match)) { if ($rest =~ m/$match/oi) { $haserror = 1; } } else { if ($rest =~ m/^w\t[45]/o) { $haserror = 1; } } if (!defined($sernrostore{$pid})) { # New PID $sernrostore{$pid} = 1; $iserr{$pid} = 0; } if ($haserror) { $iserr{$pid} = 1; local($hi,$i); $hi = $sernrostore{$pid}; for ($i = 1; $i < $hi; ++$i) { $key = $pid.".".$i; printf "%s\n",$pidstore{$key}; delete $pidstore{$key}; } $sernrostore{$pid} = 0; } if (!$iserr{$pid}) { $key = $pid.".".$sernrostore{$pid}; $sernrostore{$pid} += 1; $pidstore{$key} = $line; } else { printf "%s\n",$line; } if ($isend) { local($hi,$i); $hi = $sernrostore{$pid}; for ($i = 1; $i < $hi; ++$i) { $key = $pid.".".$i; delete $pidstore{$key}; } delete $sernrostore{$pid}; delete $iserr{$pid}; } }