S
sunckell
Hello everyone,
I am working on a script that parses a maillog (sendmail). I am
trying to gather information about particular messages from the log.
Namely the "to", "status", "date & time" , and the "msgid" from the
Exchange server that is sending the email through the sendmail server.
Since the information I need is on separate log lines, I thought I
would first read the log file for the particular "to" addresses (3
different ones) and grab the ID sendmail assigns to it, then process
the log again and add the information to a hash of hashes based on the
sendmail ID.
So in my head I figured my data structure would look something like
this:
# a hash which holds a hash of information for each sendmail ID I
grabbed from the log on the #first scan.
my %HoH = (
"$msgid" => {
'date' => "$date",
'year' => "$year",
'time' => "$time",
'exid' => "$exid",
'status' => "$status",
'email' => "$eMail"
);
I then figured I could add hashes and key value pairs while processing
each line of the log file.
I thought it all sounded good, until I tried to write it. I have a
subroutine that processes the log file. When I am done processing the
file, and I believe the hash of hashes is populated, I try to print out
the information, but I only get the last entry "infomation" that I was
able to get from the file. The hash of hashes doesn't grow as I find
more sendmail ID's and it doesn't add key value pairs as I find them.
If anyone could point me in the right direction I would be most
appreciated.
Here is the code:
---------------------------------------------------------------------
sub gather_message_info{
# @smids are the sendmail id's I gathered in a previous pass thru
the logs.
my($log, $month, $day, $hour, @smids) = @_;
my $mail_ids = join("|", @smids);
my %HoH; #initialize my hash of hashes
open(LOG,"$log") || die "Can't open $log: $! \n";
while(<LOG>){
#only want the past hours worth of emails for specified msgids
only.
next if(!/^$month\s+$day\s$hour/);
next if(!/$mail_ids/);
/^
(\S{3})\s+(\d+) # date -- 1, 2
\s
(\d+)
\d+)
\d+) # time -- 3, 4, 5
\s
(?:\S{4}) # hostname
\s
(?:\w+\[\d+\]
# service name and process ID
\s
(?:\[.{15,}?\]) # syslog ID and level
\s
(.{13,}?
# message ID
\s
(.*) # text -- 7
$/x or do
{
my $warn = "\t$_\n";
push(@warnings,$warn);
};
my $date = "$1 $2";
my $time = "$3:$4:$5";
my $hour = "$3";
my $msgid = "$6";
my $text = "$7";
%HoH = (
"$msgid" => {
"date" => "$date",
"year" => "$year",
"time" => "$time",
}
);
#add exchange id to the hash.
if($text =~ /msgid\=</){
my($ex_id) = (split /\s+/, $text)[4];
#clean up the output a little
$ex_id =~ s/msgid\=<//;
$ex_id =~ s/>,//;
$HoH{$msgid}{exid} = $ex_id;
}
if($text =~ /^to\=</){
#check status first.
my $status = (split /stat\=/, $text)[1];
if ($status =~ /Sent\s\(OK\)/){
$HoH{$msgid}{status} = $status;
}else{
next;
}
#grab the email address
my($eMail) = (split /\s+/, $text)[0];
#clean up the output a little
$eMail =~ s/to\=<//;
$eMail =~ s/>,//;
$HoH{$msgid}{email} = $eMail;
}
}
close(LOG);
return(%HoH);
}
Now if I print the %HoH with Data:
umper like so:
print Dumper \%HoH;
All I get is:
$VAR1 = {
'k21HwINE006701:' => {
'email' => '(e-mail address removed)',
'year' => 2006,
'status' => 'Sent (OK)',
'date' => 'Mar 1',
'time' => '12:58:32'
}
};
When I know I should have 10 message ids (hashes within the main hash)
with all the key value pairs filled (email, year,
status,date,time,exid, etc).
Once again thanks for the guidance.
Sincerely,
sunckell
I am working on a script that parses a maillog (sendmail). I am
trying to gather information about particular messages from the log.
Namely the "to", "status", "date & time" , and the "msgid" from the
Exchange server that is sending the email through the sendmail server.
Since the information I need is on separate log lines, I thought I
would first read the log file for the particular "to" addresses (3
different ones) and grab the ID sendmail assigns to it, then process
the log again and add the information to a hash of hashes based on the
sendmail ID.
So in my head I figured my data structure would look something like
this:
# a hash which holds a hash of information for each sendmail ID I
grabbed from the log on the #first scan.
my %HoH = (
"$msgid" => {
'date' => "$date",
'year' => "$year",
'time' => "$time",
'exid' => "$exid",
'status' => "$status",
'email' => "$eMail"
);
I then figured I could add hashes and key value pairs while processing
each line of the log file.
I thought it all sounded good, until I tried to write it. I have a
subroutine that processes the log file. When I am done processing the
file, and I believe the hash of hashes is populated, I try to print out
the information, but I only get the last entry "infomation" that I was
able to get from the file. The hash of hashes doesn't grow as I find
more sendmail ID's and it doesn't add key value pairs as I find them.
If anyone could point me in the right direction I would be most
appreciated.
Here is the code:
---------------------------------------------------------------------
sub gather_message_info{
# @smids are the sendmail id's I gathered in a previous pass thru
the logs.
my($log, $month, $day, $hour, @smids) = @_;
my $mail_ids = join("|", @smids);
my %HoH; #initialize my hash of hashes
open(LOG,"$log") || die "Can't open $log: $! \n";
while(<LOG>){
#only want the past hours worth of emails for specified msgids
only.
next if(!/^$month\s+$day\s$hour/);
next if(!/$mail_ids/);
/^
(\S{3})\s+(\d+) # date -- 1, 2
\s
(\d+)
\s
(?:\S{4}) # hostname
\s
(?:\w+\[\d+\]
\s
(?:\[.{15,}?\]) # syslog ID and level
\s
(.{13,}?
\s
(.*) # text -- 7
$/x or do
{
my $warn = "\t$_\n";
push(@warnings,$warn);
};
my $date = "$1 $2";
my $time = "$3:$4:$5";
my $hour = "$3";
my $msgid = "$6";
my $text = "$7";
%HoH = (
"$msgid" => {
"date" => "$date",
"year" => "$year",
"time" => "$time",
}
);
#add exchange id to the hash.
if($text =~ /msgid\=</){
my($ex_id) = (split /\s+/, $text)[4];
#clean up the output a little
$ex_id =~ s/msgid\=<//;
$ex_id =~ s/>,//;
$HoH{$msgid}{exid} = $ex_id;
}
if($text =~ /^to\=</){
#check status first.
my $status = (split /stat\=/, $text)[1];
if ($status =~ /Sent\s\(OK\)/){
$HoH{$msgid}{status} = $status;
}else{
next;
}
#grab the email address
my($eMail) = (split /\s+/, $text)[0];
#clean up the output a little
$eMail =~ s/to\=<//;
$eMail =~ s/>,//;
$HoH{$msgid}{email} = $eMail;
}
}
close(LOG);
return(%HoH);
}
Now if I print the %HoH with Data:
print Dumper \%HoH;
All I get is:
$VAR1 = {
'k21HwINE006701:' => {
'email' => '(e-mail address removed)',
'year' => 2006,
'status' => 'Sent (OK)',
'date' => 'Mar 1',
'time' => '12:58:32'
}
};
When I know I should have 10 message ids (hashes within the main hash)
with all the key value pairs filled (email, year,
status,date,time,exid, etc).
Once again thanks for the guidance.
Sincerely,
sunckell