Whats the recommended solution to comb apache's previous day's /var/log/httpd/error_log looking for lines that contain a certain string and email when such strings are detected?

It could be run hourly via cron and the strings in my case would be "sigkill" or "reached maxclients".

Nagios, Cacti, etc would be an overkill. I need something simple.



But if really you prefer perl, it's a little lighter than bash, but...

#!/usr/bin/perl -w

use strict;

my $cachefile="/var/cache/lastpos-apache2-scan4maxclntOrSigKill";
my $logfile="/var/log/apache2/error.log";
my $searchstr="sigkill|reached maxclients";

my $lastpos=0;
if (-f $cachefile) {
    open FH,"<".$cachefile;
    close FH;

my $newpos=(stat $logfile)[7];

open FH,"<".$logfile;
seek FH,$lastpos,0;
while (<FH>) {
    print if /$searchstr/i;
close FH;

open FH,">".$cachefile;
print FH $newpos;
close FH;
  • still, no output. – Gaia Oct 27 '12 at 14:09
  • with i modifier for case independant? – F. Hauri Oct 27 '12 at 14:14
  • don't forget to clean cache: rm /var/cache/lastpos-apache2-scan4maxclntOrSigKill – F. Hauri Oct 27 '12 at 14:16
  • yes, i delete the cache every time before i run it. – Gaia Oct 27 '12 at 14:42
  • Did you add the i modifier after if /$searchstr/i;, did you need case independant, what's the look of your searched lines exactly? – F. Hauri Oct 27 '12 at 14:53

For running periodicaly via cron, you could Us a cache to store last position in logfile than grep on newest lines:


searchstr='sigkill\|reached maxclients'

[ -f $cachefile ] && lastpos=$(<$cachefile)
[ "$lastpos" ] || lastpos=0

newpos=$(stat -c %s $logfile)

[ $lastpos -gt $newpos ] && lastpos=0

tail -c +$lastpos $logfile | grep "$searchstr"

echo $newpos >$cachefile
  • This way I can run it even hourly and it will only send me the new entries, right? – Gaia Oct 27 '12 at 13:51
  • (added a line for "touch /var/cache/lastpos-apache2-scan4maxclntOrSigKill" to avoid errors on the first run) – Gaia Oct 27 '12 at 13:54
  • it stores $lastpos in the cachefile but it outputs nothing (even with the correct value in logfile). manually doing tail -c +40667 /var/log/httpd/error_log | grep "sigkill|reached maxclients" also brings nothing. – Gaia Oct 27 '12 at 13:57
  • maybe did you need case independant: grep -i "... ? – F. Hauri Oct 27 '12 at 14:07
  • sorry, I forget the \ before | in the grep command – F. Hauri Oct 27 '12 at 14:09

There's always Perl, e.g.:

perl -ne 'print if m/sigkill|reached maxclients/i' /var/log/apache2/error_log
  • how do I make that case insensitive? mi/ ? – Gaia Oct 27 '12 at 13:27
  • @Gaia m//i, see updated answer. – Ansgar Wiechers Oct 27 '12 at 13:29
  • ahhh perl is like magic... one more thing. each line begins with the date in format "[Wed Oct 24 05:15:52 2012]". how do i pick only the prior day's (i will set to run it past midnight) or the last 24 hours, whichever is simpler? Logs are rotated weekly. – Gaia Oct 27 '12 at 13:34
  • See the answers to this question. – Ansgar Wiechers Oct 27 '12 at 14:14
  • Thanks, but I think i am better off with caching $lastpos, as suggested below. Unless awk or sed has a one-liner that can do the above and only get the last X hrs... – Gaia Oct 27 '12 at 14:35

Monit is a very lightweight system monitoring tool and will watch log files and send alerts when certain strings appear. See the documentation at http://mmonit.com/monit/documentation/monit.html#file_content_testing for usage.

  • thanks, but a 15 line script and a cron job did it. – Gaia Oct 27 '12 at 18:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.