Why isn't `tail -f … | grep -q …` quitting when it finds a match?
I'm doing a pretty standard tail
+ grep
:
tail -f some_log_file.txt | grep -q known-string
If I run the command without the -q
:
tail -f some_log_file.txt | grep known-string
I see output:
[Tue Feb 12 11:32:45 2019] known-string.
so I know the grep is matching. However when I add -q
the grep command doesn't exit, it just hangs there waiting for more output ... even though the man page says it will "Exit immediately with zero status if any match is found":
-q, --quiet, --silent Quiet; do not write anything to standard output. Exit immediately with zero status if any match is found, even if an error was detected. Also see the -s or --no-messages option.
Can anyone explain why -q
isn't causing my grep to exit? I'm trying to chain a && beep
to the end so the grep
beeps when a match is found, but unless I can make it exit that won't work.
From StackOverflow post 'grep -q' not exiting with 'tail -f':
tail -f
will read a file and display lines later added, it will not terminate (unless a signal likeSIGTERM
is sent).grep
is not the blocking part here,tail -f
is.grep
will read from the pipe until it is closed, but it never is becausetail -f
does not quit and keep the pipe open.
A solution to your problem would probably be (not tested and very likely to perform badly):
tail -f logfile | while read line; do echo $line | grep -q 'find me to quit' && break; done
You will find more information and solutions in the linked post.
grep
does exit and the pipe goes away, although tail
keeps running. This bug report log starts with a use case very similar to yours:
I want to use
tail
andgrep
to follow a file until a particular pattern appears. Buttail
does not exit whengrep
is finished.$ echo xxx > /tmp/blabla $ tail -f /tmp/blabla |grep -m1 --line-buffered "xxx" xxx
Now
tail
still tries to read and exits only if I write again into/tmp/blabla
.Is this how it's supposed to be?
The explanation there:
tail
does exit on SIGPIPE, however it will only get the signal onwrite()
, and so you need to get more data in the file beforetail
will exit.
As far as I know, this exact mechanism is very common. Many tools exit after they try to write something to a broken pipe, it's not a bug.
Then this wish came:
It's a fair point though that
tail
, since it can hang around forever should take special steps to be responsive to the other end of the pipe going away.
And finally:
Implemented in:
https://git.sv.gnu.org/cgit/coreutils.git/commit/?id=v8.27-42-gce0415f
And indeed, when I try to reproduce your problem with tail
from GNU coreutils 8.28, I cannot. The tool exits immediately.