Reputation: 2256
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.
Upvotes: 8
Views: 1644
Reputation: 70812
sed -u
for unbuffered:Lighter than awk
and grep
, using sed
could be simple, quick and efficient:
tail -f access.log | sed -une "s@/index.php@&\o7@p"
sed
will replace /index.php
by found string &
plus beep: \o7
, then print lines where something was replaced. With -u
, sed will read lines by lines, unbuffered.
path='/index.php'
tail -f access.log | sed -une "s@${path}@&\o7@p"
Upvotes: 0
Reputation: 361625
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 }'
Upvotes: 15
Reputation: 169018
Grep buffers output when standard output is not a terminal. You need to pass the --line-buffered
switch to grep to force it to flush standard output whenever it writes a line.
Upvotes: 7