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

I am trying to grep FAIL from a log file and sending mail in case there is any occurence of FAIL in the log, but i am getting below syntax error. Please help

Reason - syntax error at ./aakash_script.pl line 21, near "'FAIL' $logFile"

my $status = 0; my $logFile = "/icd/rc/genus22/logs/genus_221/v22.10-d037/lnx86_64_opt +/1/tamper.log"; if (-e $logFile) { $status = grep ': FAIL' $logFile; sendMail("kaakash", "Check Tamper Test failed", "C +heck tamper test failed.", "xyz") if ($status != 0); $status ++ ; } else { $status ++; sendMail("kaakash", "Check Tamper Test failed:", "$logFile + not found.", "xyz"); }

Replies are listed 'Best First'.
Re: how to grep from a log file
by choroba (Cardinal) on Jul 07, 2021 at 10:58 UTC
    The syntax for grep is shown in the documentation:

    grep BLOCK LIST grep EXPR,LIST

    But you used

    grep ': FAIL' $logFile

    Adding a comma will fix the syntax error, but the code won't do what you want. Grep iterates over the elements of the list, but you gave it just the file name. You need to supply the file contents instead.

    Also, you specified a string as the expression. The string is always true, so grep will return all the lines regardless of what they contain. You need to use a regular expression match or index:

    open my $fh, '<', $logFile or die $!; my $status = grep /: FAIL/, <$fh>; # or my $status = grep { -1 != index $_, ': FAIL' } <$fh>;

    Or maybe, you wanted to run the external command grep instead of the Perl's grep?

    my $status = system 'grep', ': FAIL', $logFile;

    map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]
Re: how to grep from a log file
by haukex (Archbishop) on Jul 07, 2021 at 10:52 UTC
Re: how to grep from a log file
by afoken (Chancellor) on Jul 07, 2021 at 10:57 UTC

    grep expects a list, not a filename.

    Alexander

    --
    Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)
Re: how to grep from a log file
by Marshall (Canon) on Jul 08, 2021 at 21:40 UTC
    1) How often does this script run?
    2) How do you prevent bombarding the email address with many emails related to the same error?

    Perl has a very good way of "grepping". Use the Perl way instead of calling external GREP. This will be much faster.

    Handling (2) requires knowledge of your log file which your post doesn't have.

    Update:
    This is not so good: if (-e $logFile) {}
    The log file could perhaps "go away" for a brief time during some pruning or archiving process.
    The next steps in your code are not guaranteed to work.

    Use open() to get a file handle. Process the results of that file handle. Once you have a valid file handle, what happens in the directory (like rename or even delete) doesn't matter.

    I am assuming that your process runs "in the background", a Windows Service or Unix Daemon.
    Think about what happens if you monitoring program fails or fails to start? There are a lot of issues.

    Update:

    So some code (untested) could look like this:

    my $logFile = "/icd/rc/genus22/logs/genus_221/v22.10-d037/lnx86_64_opt +/1/tamper.log"; open (my $fh, '<', $logFile) or reportErr($!); if ( grep{": FAIL"}<$fh>) #FAIL found anywhere in file! { do something... exit or return... } # text "Fail" not found if here do whatever... sub reportErr { my $error_text = shift; do something... }
    However, the problems I mentioned above still exist. If FAIL appears anywhere in the log file, this will send an email every time that this script runs! If somehow the logfile cannot be opened, same problem, this will send an email every time that this script runs!

    A working script needs to address both of these issues. I'd need to know more about your application to find the "best" answer. Basically you need some kind of a persistent flag that has the effect of "throttling down" the error emails. If your script is running continuously, you could keep this as a global variable. Another technique could be to use the file system. When sending an email create a file "last_email_sent", you could check the file modification date of that file and don't send another email unless its been say at least one hour? You don't have to put any data in the flag file itself. Its perfectly legal to have a file with 0 bytes in it. However, perhaps you could put something in this file that perhaps references a line number in the log file or perhaps a date/time value associated with the error. Maybe you don't want to keep reporting the same error over and over again? Maybe after handing an error, you just leave the log file alone, remembering that you've already reported the last error and don't report again unless a new error shows up? Anyway what you want to prevent is flooding the Error_email_box with messages.