eselement has asked for the wisdom of the Perl Monks concerning the following question:

I'm very new to Perl, learning as I go, but I've hit a roadblock and I'm not sure if the problem is with my logic or simple lack of experience in Perl--or both.

Basically, the script opens an error log, reads through each line looking for a specific error message, and then sends an email if the error message exists. That much I have working. But it gets complicated because the plan is to have the script run every X minutes to search for new error messages and ignore past messages.

What I wish to do is pull any error message that occurs on today's date and send an email describing the error. This wouldn't be a problem except that I don't want the script to pick up error messages that occured in the past (after the message was sent) and continue sending messages--the error log could possibly be reporting the same error several times a minute. Further, once the problem is resolved, I don't want the script to continue sending messages because it still sees today's date and the error text in the log file. But I do want it to continue searching for future errors every time it runs.

I've tried using Add_Delta_DHMS to only report errors that occured X minutes ago, but that does no good because what I need is it to look at the range of minutes in between as well.

Here's the code as the script currently exists:

open(PCC_ERR, "ErrLog.PCC") or die "Cannot open ErrLog.PCC"; #PCC_ERR + is the filehandle. Opens error log use Date::Calc(Today); # needed for calculating 'friendly' dates ($year, $month, $day) = Today; # Go through each line of the error log and only report if a line cont +ains today's date and error codes 3022 or 3186 for $line (<PCC_ERR>) { if ($line =~ /$month-$day-$year/ && $line =~/3022|3186/) { use Net::SMTP; # If the condition is met, send an email with err +or message $smtp = Net::SMTP->new('smtp.server'); # connect to an SMTP se +rver $smtp->mail('email.address'); # use the sender's address h +ere $smtp->to('recipient.address'); # recipient's address $smtp->data(); # Start the email $smtp->datasend("To: recipient.address\n"); $smtp->datasend("From: email.address\n"); $smtp->datasend("\n"); $smtp->datasend("Error Report for $month-$day-$year: Errors Fo +und on Server!\n"); $smtp->dataend(); # Finish sending the mail $smtp->quit; # Close the SMTP connectio +n last; # break loop if error found } } close(PCC_ERR);


I'm hoping someone can help me with the logic if not the code, because I feel like I'm just missing something or making it harder than it is. Thanks!

Replies are listed 'Best First'.
Re: Using Date::Calc with an error log
by wind (Priest) on Jul 12, 2007 at 00:41 UTC
    What is the format of your datetime value? Take a look at the cpan module Date::Parse. It will enable you to translate the string time into epoch, which is much easier to use to test for ranges.

    Observe the following script:
    use Date::Parse qw(str2time); my $TIME_DELTA = 5 * 60; # In Seconds # my $mintime = time - $TIME_DELTA; my $mintime = 1184200080 - $TIME_DELTA; # Harded time of '11/Jul/2007: +17:28:00' while (<DATA>) { next if ! m{(\d+/\w+/\d+:\d+:\d+:\d+)}; my $errtime = str2time($1); next if $errtime < $mintime; print "$_"; } __DATA__ 192.168.130.2 - - [11/Jul/2007:17:19:05 -0700] 192.168.174.0 - - [11/Jul/2007:17:19:57 -0700] 192.168.200.4 - - [11/Jul/2007:17:20:07 -0700] 192.168.179.60 - - [11/Jul/2007:17:20:10 -0700] 192.168.174.0 - - [11/Jul/2007:17:20:21 -0700] 192.168.204.206 - - [11/Jul/2007:17:21:20 -0700] 192.168.65.202 - - [11/Jul/2007:17:21:20 -0700] 192.168.32.139 - - [11/Jul/2007:17:21:46 -0700] 192.168.227.192 - - [11/Jul/2007:17:22:28 -0700] 192.168.128.135 - - [11/Jul/2007:17:22:43 -0700] 192.168.104.11 - - [11/Jul/2007:17:23:45 -0700] 192.168.57.210 - - [11/Jul/2007:17:24:00 -0700] 192.168.115.28 - - [11/Jul/2007:17:24:55 -0700] 192.168.112.24 - - [11/Jul/2007:17:25:11 -0700] 192.168.140.141 - - [11/Jul/2007:17:25:25 -0700] 192.168.100.206 - - [11/Jul/2007:17:26:31 -0700] 192.168.140.141 - - [11/Jul/2007:17:26:56 -0700] 192.168.172.3 - - [11/Jul/2007:17:27:00 -0700] 192.168.71.179 - - [11/Jul/2007:17:27:43 -0700] 192.168.81.11 - - [11/Jul/2007:17:27:45 -0700] 192.168.40.238 - - [11/Jul/2007:17:27:52 -0700] 192.168.38.255 - - [11/Jul/2007:17:27:53 -0700]
    - Miller
Re: Using Date::Calc with an error log
by chrism01 (Friar) on Jul 12, 2007 at 04:07 UTC
Re: Using Date::Calc with an error log
by grep (Monsignor) on Jul 12, 2007 at 00:32 UTC
    For this type of application I'd skip Date::Calc, unless you need it for some other reason. Go with epoch seconds using localtime and Time::Local. You'll have a much easier time checking ranges down to the second.