Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

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

I have the following command

tail -f development.log | grep "something rare"

is there an easy way like pipeing it to somthing that beeps? like

tail -f development.log | grep "something rare" | beep

if so will the grep output still be shown?

share|improve this question
    
there is a beep program with is in the default repo for debian and variants just apt-get install beep but it doesn't work with the piping this way –  Jakob Cosoroaba Sep 7 '09 at 13:51
add comment

6 Answers

up vote 6 down vote accepted

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
share|improve this answer
    
sorry but this is not working, it doesn't beep or prints anything –  Jakob Cosoroaba Sep 7 '09 at 13:49
2  
Although direct output of tail -f is immediate, it gets buffered as soon as it goes through a pipe. You have to wait for enough "something rare" before observing anything. –  mouviciel Sep 7 '09 at 15:00
    
You could pass the output through sed or similar (between tail and grep) to with a regexp replace the something rare with itself many times. How many times it needs to be done depends on how much the pipe is buffered. –  David Spillett Sep 7 '09 at 19:57
4  
@David - That is a hit-and-miss approach. If you want to unbuffer the data passed via a pipe, use any of the methods described in these answers: stackoverflow.com/questions/1000674/turn-off-buffering-in-pipe –  nagul Sep 8 '09 at 16:28
add comment

The watch command has an --beep option, and you can set the polling interval as well, but the standard with 2 sec should be ok

watch --beep 'tail development.log | grep "something rare"'
share|improve this answer
    
Note, watch works by running your parameter/command every (interval) sections then coming the results to the previous run. Thus you'll want to use the normal version of the tail command, instead of using tail -f –  RyanWilcox Aug 28 '12 at 19:14
add comment

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. ;-)

share|improve this answer
add comment

GNU screen has a built-in feature to beep when a given window changes: see the relevant section of the man page.

Headline summary:

$ screen
$ tail -f yourfile.log    # inside the screen session
<C-a> M    # "Window 0 (bash) is now being monitored for all activity."

As pointed out in comments, this will beep on every new log entry, not just those that match "something rare", so this doesn't do quite what the OP asked for. Still a useful trick to know IMHO.

You can get the best of both worlds by opening two screen windows (<C-a> c to open a window, <C-a> <C-a> to toggle between two windows):

  1. monitored, with tail -f yourfile.log | grep 'something rare'
  2. unmonitored, with a plain tail -f yourfile.log

Then you can sit watching the log scroll past in window 2, and you'll get beeped from window 1 when "something rare" occurs.

screen is awesomely versatile - I highly recommend reading up on it.

share|improve this answer
    
That wouldn't beep only on "something rare", would it? –  nagul Sep 7 '09 at 19:06
    
It would if all that was happening in that particular window is tail -f yourfile.log | grep something\ rare rather than just the tail -f logfile –  David Spillett Sep 7 '09 at 19:58
    
Oops, I didn't notice that he only wanted a beep on something rare. Edited to reflect this. The grep would work, but then he wouldn't see the rest of the log, only the rare lines - as I understand it he wants to be able to watch the whole log scrolling past, but be alerted on specific events. –  Sam Stokes Sep 8 '09 at 9:38
add comment

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.

share|improve this answer
add comment

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.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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