You should kill it explicitly
seq 1 10 > file
tail -f file | { sed /7/q; pkill -PIPE -xg0 tail; } | tee output
pkill -PIPE -xg0 tail
means
send a SIGPIPE
signal to the process named exactly tail
from the same process group as ourselves.
This assumes that there is no other tail
running in the same process group. If the command is run from an interactive terminal (from a shell with job control), it should be safe, as each pipeline is then run in its own process group (aka job). In a shell without job control (e.g. in a script), we could wrap the pipeline in a separate shell where the job control is explicitly turned on:
sh -mc 'tail -f file | { sed /7/q; pkill -PIPE -xg0 tail; }' | tee output
But GNU tail kills itself
If you're using a Linux machine with bash and coreutils, you will notice that everything falls into place, and there's no need of any kill
whatsoever; tail
will simply terminate by itself:
debian$ tail -f file | sed /2/q
1
2
debian$ # WOW!
That's because the tail
from GNU coreutils is using a smart trick to determine if its stdout is still writable: it's polling it for a "ready for reading" condition, which on the writing end of a pipe will only happen in case of error, as when its other end has been closed. If that's the case, then tail
just kills itself with a SIGPIPE
signal. Quoting from its source code:
FD_SET (STDOUT_FILENO, &rfd);
/* readable event on STDOUT is equivalent to POLLERR,
and implies an error condition on output like broken pipe. */
if (select (STDOUT_FILENO + 1, &rfd, NULL, NULL, &delay) == 1)
die_pipe ();
[In fact, other systems may POLLHUP
or POLLHUP|POLLIN
instead of POLLERR
, but this doesn't matter in practice]
GNU tail only does this on pipes, not on sockets or ttys (which means that that doesn't work with ksh93, which is using kneecapped unix-domain sockets to implement its "pipes").
Also (AFAIK) only GNU tail
does this at all, and only since version 8.28; even on Linux, busybox tail
does not.
That means that using tail -f | quit_at_some_point
(from many answers here) is still very much hit-and-miss, and may actually never terminate.
tail -f
hangs around only until its sleep interval ends. So, in order to make it terminate faster, invoke it with--sleep-interval=N
, e.g.tail -f -s 0.01 logfile | sed '/special string/q' | tee output.txt
. – Amir Oct 20 '20 at 06:35special string
, matching anything in the log file when interpreted as a regular expression? – Kusalananda Oct 20 '20 at 07:47bash
, then mention that in the question. If you have found a solution, then post it as an answer along with an explanation of the issue and of how your solution solves the issue. – Kusalananda Oct 20 '20 at 09:07/proc
filesystem, does not assume that they're both part of the same process group, does not assume that pipes aren't implemented with sockets (as in ksh), and will happen immediately, not when the writer tries to write something else (which may never come). – Oct 25 '20 at 18:28sed
, one that will terminate when done. When it terminates the pipes will be closed, andtail
will exit. considerawk
. – ctrl-alt-delor Nov 17 '20 at 20:37