2

I am creating a script that will email errors/warnings from a log. I would like to have this sent every half hour but I only want to send it if there is a new entry. How would I grep out only the last half hour of errors?

The time stamp in the log is in the following format.

< Aug 1, 2016 2:15:29 PM MDT> < Error details.....>

The script so far is:

#!/bin/bash
cat /var/log/logfile.log | egrep -i "error|warning" | tee -a /tmp/log.tmp

"get only last 30 min of errors" | mail -s "Errors/Warning" user@email.com

Is it possible to convert the time stamps (Aug 1, 2016 2:15:29 PM MDT) to epoch time then compare it to the current epoch time or is there a way with sed/awk/perl to get the last 30 minutes?

  • 1
    Get a baseline copy of your log file; run a script every 30 minutes and diff log file to the baseline file; massage the diff output to filter out extra characters; if there is a difference, send email with the difference lines in the context; make the current logfile the baseline file for the next run. This assumes you want to run this process continuously. – MelBurslan Aug 4 '16 at 22:46
  • Does every line in the log contain a timestamp? – glenn jackman Aug 5 '16 at 19:42
2

For conver to epoch, You can use the following statement :

# date +%s -d"Aug 1, 2016 2:15:29 PM MDT"
1470082529

For convert epoch to UTC, You can use :

# date -d @1470082529
Tue Aug  2 00:45:29 IRDT 2016  #### on Linux Box

# date -r 1470082529
Tue Aug  2 00:45:29 IRDT 2016 ###on BSD box
1

I'd use perl's File::Tail module. I don't have time to write an example now, but in perlish pseudocode, it would look something like this:

#! /usr/bin/not-actually-perl

use strict;
use File::Tail;

use Net::SMTP or Mail::Mailer or one of the squillion other
  perl mail sending modules;

open a File::Tail file handle to your log file

my $now=time();

my @lines = ();

while (read the File::Tail handle) {
  push @lines, $_;
  if (time() > ($now + 1800 seconds) ) {
    $now=time();
    email the @lines array to you@your.address;
    @lines=();
  }
}

An actual working script would probably be less than 10 lines longer than the above, and most of that would be setting up the headers for the email.

and a few more lines to trap various signals to email what it has now in @lines before suspending or quitting.

See the man pages for File::Tail and Net::SMTP (or whatever) for exact details.

0

Great ideas, the simplest is @MelBurslan suggestion to diff the files.

#!/bin/sh

MAILTO=user@email.com
OFILE=/var/tmp/alerts.tmp
LOG30=/var/tmp/LOG30
LOGNOW=/var/tmp/LOGNOW
HOST=`hostname`

# setup file
if [ -f ${OFILE} ]; then
  cat /dev/null > ${OFILE}
else
  touch ${OFILE}
fi


cat /var/log/logfile.log | egrep -i "error|warning" | tee -a ${LOGNOW}

diff ${LOG30} ${LOGNOW} | tee -a ${OFILE}

if [ -f ${OFILE} ]; then
  echo "Errors" | cat - ${OFILE} > temp && mv temp ${OFILE}
  mailx -r root@server.com -s "Errors" ${MAILTO} < ${OFILE}
fi

rm ${LOG30}
mv ${LOGNOW} /var/tmp/LOG30
rm ${OFILE}

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.