Searching for a string in a log file with little movement

I have a script which tails a log file and if it finds certain strings in the data tailed it sends an email, basically like this:

tail -f logfile > tmp.file &
sleep 10
kill $!
STRING=$(grep -c "string" tmp.file)

[ $STRING -gt 2 ] && echo $STRING | mailx -s "Warning.." admin@123.com

When the string is found I sleep the script for 15mins in order to suppress duplicate alerts.. but sometimes nothing is written to the error log in hours so tail -f will find the same string again when the script reruns.

Anyone have a way around this, basically i want to search for the string only if there is activity in the error log.

Why not monitor the latest time stamp on the logfile, it will tell you when it's last been modyfied, if it differs from last check, then there are some lines that has been written to it, tail them out and search for your string.
ie:

 ~> ls -l /var/log/messages
-rw-r----- 1 root adm 520646 27 mar 21:41 /var/log/messages
~> date
sat mar 27 21:52:07 CET 2010
~> /etc/init.d/sysklogd restart
Restarting system log daemon....
~> ls -l /var/log/messages
-rw-r----- 1 root adm 520733 27 mar 21:52 /var/log/messages

You can even use some "wc -l" on the file to make sure it's only the latest written lines you're tail'ing from it.

empty tmp.file first.

rm -f tmp.file

This problem seems to be due to the way tail -f works, it writes the last ten lines of the log file to the tmp.file even if there isn't any movement in the log file. I wonder is it possible to turn off that behavior?

Anyway I am going try get round this by using the file attributes of the error log, thanks Redhead.

Hi rdcwayx, i already null the tmp.file before the script exists.

what about the -s (sleep interval) option of tail ?

Hi Frans, how would you use the -s argument in this case?

Hi moxy,

i'm not sure if its what exactly you want but try it, then tell us if it works or not, i couldnt test my code:

occ=`grep -c "string" logfile`

num_of_occ=`awk -v pattern="string" -v last="$occ" 
'$0~pattern{i++} i==last{print NR;exit}' logfile`

sleep 900

occ_=`grep -c "string" logfile`

num_of_last_occ=`awk -v pattern="string" -v lastocc="$occ_2" 
'$0~pattern{i++} i==lastocc{print NR;exit}' logfile`

if [ $num_of_occ -lt $num_of_last_occ ]; then mailx -s "WARNING!" admin@123.com

Actually only "grep -c" could be enough too :smiley:

occ=`grep -c "string" logfile`

sleep 900

occ_=`grep -c "string" logfile`

if [ occ -lt occ_ ]; then mailx -s "WARNING!" admin@123.com 

Comparing the string counts before and after is perfect, thanks a lot EAGL�.

Your wellcome, but i thought about what if your logfile appends to a new one, could this solution fail?

like this: lets say when script started it considers the logfile1.bak but after a while (15 minutes) the new logfile starts and code checks strings in new logfile and occurances of string in logfile.txt could be less than the occurances of backup logfile.

logfile.txt
logfile1.bak

Try below code to avoid the last ten lines in tail output.

STRING=$(awk 'NR>10 && /string/' tmp.file)
tail -f -n0