Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

'tail -f' doesn't give single lines when piped through grep'

Tags:

bash

I am launching a website, and I wanted to setup a Bash one-liner so when someone hits the site it would make a beep using the internal buzzer.

So far it's working using the following.

tail -f access_log | while read x ; do echo -ne '\007' $x '\n' ; done

Tail follows the access_log and dumps to STDOUT, get STDOUT line at a time, echo the line with '\007' "internal beep hex code", and done...

This works like a beauty... Every hit shows the line from the log and beeps... However, it got annoying very quickly, so ideally I wanted to filter the tail -f /access/log before it's piped into the while so that read only gets lines I care about. I was thinking grep "/index.php" would be a good indication of visitors...

This is where the issue is...

I can do...

tail -f access_log | while read x ; do echo -ne '\007' $x '\n' ; done

beeps on everything and i can do...

tail -f access_log | grep "/index.php"

and pages are shown with no beep, but when i do

tail -f access_log | grep "/index.php" | while read x ; do echo -ne '\007' $x '\n' ; done

Nothing happens, no line from log, no beep.

I think the grep is messing it up somewhere, but I can't figure out where. I'd love it to be a one liner, and I know it should really be done in a script and would be easier, but it doesn't explain why the above, which I think should work, isn't.

like image 226
Phil Poore Avatar asked May 01 '13 17:05

Phil Poore


People also ask

How do I grep specific lines in a file?

The grep command searches through the file, looking for matches to the pattern specified. To use it type grep , then the pattern we're searching for and finally the name of the file (or files) we're searching in. The output is the three lines in the file that contain the letters 'not'.

How do I print multiple lines in grep?

You can use grep with -A n option to print N lines after matching lines. Using -B n option you can print N lines before matching lines. Using -C n option you can print N lines before and after matching lines.

How do you pipe a grep output?

grep is very often used as a "filter" with other commands. It allows you to filter out useless information from the output of commands. To use grep as a filter, you must pipe the output of the command through grep . The symbol for pipe is " | ".

How do you grep multiple lines after a match?

For BSD or GNU grep you can use -B num to set how many lines before the match and -A num for the number of lines after the match. If you want the same number of lines before and after you can use -C num . This will show 3 lines before and 3 lines after.


1 Answers

Grep's output is buffered when it's used in a pipe. Use --line-buffered to force it to use line buffering so it outputs lines immediately.

tail -f access_log | grep --line-buffered "/index.php" | while read x ; do echo -ne '\007' $x '\n' ; done

You could also combine the grep and while loop into a single awk call:

tail -f access_log | awk '/\/index.php/ { print "\007" $0 }'
like image 170
John Kugelman Avatar answered Sep 19 '22 15:09

John Kugelman