Home » Questions » Computers [ Ask a new question ]

how to beep on tail -f event

how to beep on tail -f event

I want my PC to make a system beep on every tail event

Asked by: Guest | Views: 382
Total answers/comments: 4
bert [Entry]

"Just define beep as following:

beep() { read a || exit; printf ""$a\007\n""; beep; }

Then, you can use your command:

tail -f development.log | grep ""something rare"" | beep"
bert [Entry]

"You can stop the output from being buffered in the grep command.
See man grep for details.

You can pipe the grep output into beep.

The following example is from man beep...

As part of a log-watching pipeline

tail -f /var/log/xferlog | grep --line-buffered passwd | \
beep -f 1000 -r 5 -s

There's a lot of good stuff in those manuals. If only we didn't have to read them to find it. ;-)"
bert [Entry]

"Hm, tricky. We could perhaps do something like this?

for i in `find | grep 7171`; do beep; echo $i; done

Or in your case

for i in `tail -f development.log | grep ""something rare""`; do beep; echo $i; done

It seems to be doing some buffering though. I'll look if there's a way to turn off this buffering by the for loop.

Apparently, you should be able to adjust pipe's buffering by using ulimit -p but that keeps complaining about Invalid argument to me. I've also found a post that claims you need to recompile kernel to change this limit."
"Hm, tricky. We could perhaps do something like this?

for i in `find | grep 7171`; do beep; echo $i; done

Or in your case

for i in `tail -f development.log | grep ""something rare""`; do beep; echo $i; done

It seems to be doing some buffering though. I'll look if there's a way to turn off this buffering by the for loop.

Apparently, you should be able to adjust pipe's buffering by using ulimit -p but that keeps complaining about Invalid argument to me. I've also found a post that claims you need to recompile kernel to change this limit."
bert [Entry]

"In a previous job, I couldn't get a reliable watcher with just command-fu, so I had a wrapper script like the one below, which inspected the file every poll_duration seconds and grepped the new lines for the interested phrase.

#!/bin/bash

file=$1
phrase=$2
poll_duration=$3

typeset -i checked_linecount
typeset -i new_linecount
typeset -i new_lines
let checked_linecount=new_linecount=new_lines=0
echo ""Watching file $file for phrase \""$phrase\"" every $poll_duration seconds""

while [ 1 ]
do
let new_linecount=`wc -l $file| awk '{print $1}'`
if [[ $new_linecount > $checked_linecount ]]; then
let ""new_lines = $new_linecount-$checked_linecount""
head --lines=$new_linecount ""$file"" | tail --lines=$new_lines | grep ""$phrase"" && beep
let checked_linecount=$new_linecount
fi
sleep $poll_duration
done

This was on a Unix machine. On Linux, you can go one better by using its inotify filewatcher interface. If this package (inotify-tools on Ubuntu) is present, replace

sleep $poll_duration

with

inotifywait -e modify ""$file"" 1>/dev/null 2>&1

This call blocks till the file is modified. The blocking version is almost as efficient as what you'd get with the tail -f version if pipe could be configured to work without buffering.

Note: The script first does a head --lines=$new_linecount to ensure that lines added to the file after we checked it do not skew the chunk of the file that gets checked in this loop."