John W. Krahn wrote:
Tom Smith wrote:
I'm writing a Perl script to parse 31 maillog files. The files are named
maillog, maillog.1, and so on up to 31. This is the default logrotate
scheme for naming rotated logs.

My current order for processing these files is this:

1) Open the directory.
2) List maillog* files in the directory and assign them to @maillog.
3) Open each file in @maillog and search it for two specific strings.
Assign matching strings to @parsedmail.
4) Print @parsedmail.

I've tested the search string on a single maillog file and it works as
expected, but putting this script together doesn't work correctly. I
think it has something to do with the way I'm trying to pass the array
to open(FILE...). The script is listed below.

(Note that the maillogs in questions were moved from our mail server to
a Windows machine for parsing. Also, the script is being run from the
directory that contains the maillogs--hence the "." for the DIR to open.
And "print @maillog" is hashed out as it tested good--that is, is prints
the array and contains the file names I expected to be there.)

#!C:\Perl\bin\perl.exe

use strict;
use warnings;
use Carp;

my @maillog;
opendir(DIR, '.') or croak "Can't open .$!";
while ($_ = readdir(DIR)) {
   if($_ =~ /^maillog.*$/) {
       push(@maillog,$_);
   }
}
closedir DIR;
#print @maillog;

my @parsedmail;
while ($_ = @maillog) {
   open(FILE,'<$_') or croak "Can't open $_$!";
   while($_ = <FILE>) {
       if($_ =~ /.*imapd.*Log.*user.*$/ || /.*pop3d.*Log.*user.*$/) {
           push(@parsedmail,$_);
       }
   }
   close(FILE);
}
print @parsedmail;


The error I get after executing this script is: "Can't open 32No such
file or directory at H:\User Files\Mail Logs\parse.pl line 31" Maybe a
coincidence, but "32" is the number of maillog files in this directory.

No it is not a coincidence.  At the line:

while ($_ = @maillog) {

When you use an array in a scalar context (like you are here) it evaluates to
the number of elements in the array so the number of elements is assigned to
the scalar variable.


Can anyone offer any advice for correcting this?

You could use some of Perl's idioms to do what you want:

#!C:\Perl\bin\perl.exe
use strict;
use warnings;

@ARGV = glob 'maillog*' or die "No maillog files found.\n";

while ( <> ) {
    print if /(?:imapd|pop3d).*?Log.*?user/;
    }

Ok,  here's the script that worked...

----------
#!C:\Perl\bin\perl.exe

use strict;
use warnings;
use Carp;

@ARGV = glob 'maillog*' or croak "Can't find any maillogs. $!";
open(FILE,'>parsedmail.txt') or croak "Can't open parsedmail.txt. $!";
while ( <> ) {
   print FILE if /.*imapd.*Log.*user.*$/ || /.*pop3d.*Log.*user.*$/;
}
close FILE;

@ARGV = glob 'messages*' or croak "Can't find any maillogs. $!";
open(FILE,'>parsedmessages.txt') or croak "Can't open parsedmessages.txt. $!";
while ( <> ) {
   print FILE if /.*imapd.*Log.*user.*$/ || /.*pop3d.*Log.*user.*$/;
}
close FILE;
----------

This outputs the expected data to the two files in question. I'm rackin' my brain a bit over something else, now. (If you haven't noticed yet, I'm quite new to Perl.)

I need to sort this output by day, then by time. Here's a sample of the first few columns of the maillog and messages files:

---------- maillog
Dec  5 13:51:55 server ipop3d...
Dec  5 13:51:55 server ipop3d...

---------- messages
Dec 27 13:23:43 server ipop3d
Dec 27 11:27:17 server imapd

Basic Linux log files.

Can anyone point me in the right direction for doing this? I'd like to understand the why as well as the how so pointers to docs would be nice, I'm just not getting the sort() docs at perldoc.perl.org.

Thanks again for all the help!

Reply via email to