CGI/Perl Guide | Learning Center | Forums | Advertise | Login
Site Search: in

  Main Index MAIN
INDEX
Search Posts SEARCH
POSTS
Who's Online WHO'S
ONLINE
Log in LOG
IN

Home: Need a Custom or Prewritten Perl Program?: I need a program that...:
Log monitoring script help

 



liton79
Novice

Jan 18, 2014, 8:17 AM

Post #1 of 4 (11944 views)
Log monitoring script help Can't Post

 
Hi Gurus,

I am trying to build a script that will check for multiple patterns in a log file and will send the matching lines plus more details of the error by email (i.e, . the email should contain, 10 lines before the pattern matching lines + pattern matching line + 10 lines after the pattern matching line).

I have started building my script as below. I am new in perl and getting few obstracles and will appreciate if any of you kindly help me to finish this.


Here are my problems:

P:1

Original log file name = abcEarlyCheckout.out.2014.01.17T04.35.02.log
This log file will be produced once daily but I am unable to assign log with with $todaydate variable plus the '*' as perl does not recognize '*'.

Trying to assign the log file in the script as:
$log="abcEarlyCheckout.out.2014.01.17.$todaydate.*.log";


P:2
Now that I am able to search the pattern and get the error line, how can I include pre and post matching pattern lines (10 lines before the pattern matching lines + pattern matching line + 10 lines after the pattern matching line) in my logic so that the email will have the detail of the error lines?




Code
#!/usr/bin/perl 

$todaydate=`date +"%Y.%m.%d"`;
open ( FILE, "> error.txt" ) || die "Cannot open " ;

$log="abcEarlyCheckout.out.2014.01.17.$todaydate.*.log";

if (-e $log)
{
open (LOGFILE, $log) or die ("Could not open log file.\n");
while(<LOGFILE>)
{

chomp;
if (/FATAL/)
{
print FILE "Script has failed with below errors, please investigate.\n\n ";
print FILE $_;
}
}
close(LOGFILE);
}
else
{
print FILE "Job did not run today, please investigate. \n";
}
close (FILE);

$to = "abc\@gmail.com";
$from = "abc\@gmail.com";
$subject = 'abcEarlyCheckout error';


my $message;
{
local $/ = undef;
open (ERROR, "error.txt") or die "file does not exists";
$message .= <ERROR>;
close FRROR;
}

open(MAIL, "|/usr/sbin/sendmail -t");

# Email Header
print MAIL "To: $to\n";
print MAIL "From: $from\n";
print MAIL "Subject: $subject\n\n";
# Email Body
print MAIL $message;

close(MAIL);
#print "Email Sent Successfully\n";

Frown


(This post was edited by FishMonger on Jan 18, 2014, 8:26 AM)


FishMonger
Veteran / Moderator

Jan 18, 2014, 9:11 AM

Post #2 of 4 (11938 views)
Re: [liton79] Log monitoring script help [In reply to] Can't Post

Perl does recognize '*'. The problem is your misunderstanding on how to use it in filename expansion.

If you print out your $log var, you'll see that its value is: "abcEarlyCheckout.out.2014.01.17.2014.01.17.*.log". I doubt that's what you expected/wanted.

You need to use the glob function or the <> diamond operator to have * used as a wild card in filename expansion.
http://perldoc.perl.org/functions/glob.html

e.g.,

Code
my $logfile = glob "abcEarlyCheckout.out.$todaydate.*.log";


Your script has many other issues that need fixing, but I don't want to overwhelm you with a major critique.

There are multiple ways to get the range of lines before and after the matching line. The most common would be to load the file into an array and loop over the array. Doing that will make it easy to output the 10 array elements before and after the match.


liton79
Novice

Jan 20, 2014, 9:59 AM

Post #3 of 4 (11900 views)
Re: [FishMonger] Log monitoring script help [In reply to] Can't Post

ok - thank you for the help. I am able to read the proper file now.

Now that I have loaded the file into an array, I am still struggling with printing 10 lines before and after the matching line.

Here is my revised code….



my $LOGFILE = glob "abcEarlyCheckout.out.$todaydate*.log";
my $search_string = "FATAL";

if (-e $LOGFILE)
{
open(FILE, "< $LOGFILE") or die "Could not open log file.\n";
if (~ m/$search_string/gi)
{
@lines = <FILE>;
}
}
else
{
@lines = 'Job did not run today, please investigate.';
}
close (FILE);


####E-mail the status ####

$to = "abc\@gmail.com";

$from = "abc\@gmail.com";

$subject = 'abcEarlyCheckout error';


#my $message;
open(MAIL, "|/usr/sbin/sendmail -t");

# Email Header
print MAIL "To: $to\n";
print MAIL "From: $from\n";
print MAIL "Subject: $subject\n\n";
# Email Body
print MAIL @lines;

close(MAIL);


Laurent_R
Veteran / Moderator

Jan 20, 2014, 12:05 PM

Post #4 of 4 (11892 views)
Re: [liton79] Log monitoring script help [In reply to] Can't Post


In Reply To

Code
      open(FILE, "< $LOGFILE") or die "Could not open log file.\n"; 
if (~ m/$search_string/gi)
{
@lines = <FILE>;
}



Hmm, not entirely sure what you are trying to do, but the second line in the code above does not make sense: when you are trying this regex match, you still haven't read any line from the file, so this is doomed to fail (in addition to the syntax that most probably does not work).

You should probably slurp your file into the @lines array, and then go through the array to look for a match. When you get a match, then you can print the lines before and after the line where the match occurred.

Something like this (quick untested code):


Code
open my $FILE, "<", $LOGFILE" or die "Could not open log file.\n"; 
my @lines = <$FILE>;
for my $i (0..$#lines) {
if ($lines[$i] ~= $search_string/g) {
my $min = $i > 9 ? $i - 10 : 0;
print @lines[$min..$i+10];
}
}


There are other problems with your code, but at least this should give you a more or less proper algorithm.

 
 


Search for (options) Powered by Gossamer Forum v.1.2.0

Web Applications & Managed Hosting Powered by Gossamer Threads
Visit our Mailing List Archives