2

I want to terminate the tail command after having the match found and until then all the lines are written to another file.

tail -f logfile | sed '/special string/q'  | tee output.txt

Output.txt will have the lines until special string is found. But the problem is, after that I want to end the tail command.

12
  • 6
    Does this answer your question? tail a log util keywords found or timeout Commented Oct 20, 2020 at 6:08
  • In my experimentation, it seems like 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
    Commented Oct 20, 2020 at 6:35
  • my script still is in the same line, it is not terminating there. @Amir Commented Oct 20, 2020 at 6:43
  • Is your pattern, special string, matching anything in the log file when interpreted as a regular expression?
    – Kusalananda
    Commented Oct 20, 2020 at 7:47
  • 2
    How to kill the tail -f process after finding the special string? -- same class? Commented Oct 20, 2020 at 12:14

2 Answers 2

6

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.

2

Given the following logfile:

one
two
three
special string
four

And the following command

$ tail -f logfile | sed '/special string/q'  | tee output.txt

I get the following output:

one
two
three
special string

And then both tail and sed exit successfully. So your own example, at least on my computer, works exactly as you described. To further verify this, given the following file

one
two
three
four

I get no output, and the command hangs, waiting for the special string. When I, then, add it using the command echo special string >> logfile from a separate terminal, the original command succesfully exits again.

So everything seems to work correctly, right? If not, please let me know what you expected. In any case, thank you for learning me a cool new trick which I will undoubtedly use in the future!

3
  • 2
    It works for you because the tail from coreutils (the default on Linux) does a very smart select() trick to determine if its stdout pipe is still writable , and if it's not, it kills itself with SIGPIPE. That's unfortunately not the case everywhere.
    – user313992
    Commented Oct 25, 2020 at 19:08
  • Interesting! Where can I learn more about this trick? Commented Oct 25, 2020 at 19:19
  • See the source code. Unfortunately, that doesn't work with a shell like ksh93, which is using Unix sockets to implement its pipes.
    – user313992
    Commented Oct 25, 2020 at 19:23

Not the answer you're looking for? Browse other questions tagged .