Why isn't `tail -f … | grep -q …` quitting when it finds a match?

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 like SIGTERM 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 because tail -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 and grep to follow a file until a particular pattern appears. But tail does not exit when grep 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 on write(), and so you need to get more data in the file before tail 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.

Tags:

Linux

Grep

Tail