make tail -f exit on a broken pipe

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP











up vote
4
down vote

favorite












I want to watch a file until a bit of text appears



I found this answer: `tail -f` until text is seen



but when I tried it on ubuntu, it doesn't exit:



$ echo one > test.txt
$ echo two >> test.txt
$ echo three >> test.txt
$ echo four >> test.txt
$ cat test.txt | sed '/w/ q'
one
two
$


works as expected. however when I try to tail the file



$ tail -f test.txt | sed '/w/ q'
one
two


it never exits. tail does not stop even though the pipe is broken.



Does anybody know how to make tail exit when sed exits?







share|improve this question


















  • 1




    Similar: unix.stackexchange.com/a/366806/22565
    – Stéphane Chazelas
    Jan 10 at 16:51










  • I don't think either of those are similar to this question. One is about writing your own program (in golang) that exits when the pipe is broken. This question is specifically about tail -f and asking why something in a previous answer doesn't work.
    – Alex028502
    Jan 10 at 17:15










  • The answers there explain why tail -f is not killed when sed exits, when the pipe is broken (because it doesn't write anything after) and how to work around it.
    – Stéphane Chazelas
    Jan 10 at 17:16










  • funny thing is what I am trying to do is an accepted answer here: unix.stackexchange.com/a/45943/158192
    – Alex028502
    Jan 10 at 17:20














up vote
4
down vote

favorite












I want to watch a file until a bit of text appears



I found this answer: `tail -f` until text is seen



but when I tried it on ubuntu, it doesn't exit:



$ echo one > test.txt
$ echo two >> test.txt
$ echo three >> test.txt
$ echo four >> test.txt
$ cat test.txt | sed '/w/ q'
one
two
$


works as expected. however when I try to tail the file



$ tail -f test.txt | sed '/w/ q'
one
two


it never exits. tail does not stop even though the pipe is broken.



Does anybody know how to make tail exit when sed exits?







share|improve this question


















  • 1




    Similar: unix.stackexchange.com/a/366806/22565
    – Stéphane Chazelas
    Jan 10 at 16:51










  • I don't think either of those are similar to this question. One is about writing your own program (in golang) that exits when the pipe is broken. This question is specifically about tail -f and asking why something in a previous answer doesn't work.
    – Alex028502
    Jan 10 at 17:15










  • The answers there explain why tail -f is not killed when sed exits, when the pipe is broken (because it doesn't write anything after) and how to work around it.
    – Stéphane Chazelas
    Jan 10 at 17:16










  • funny thing is what I am trying to do is an accepted answer here: unix.stackexchange.com/a/45943/158192
    – Alex028502
    Jan 10 at 17:20












up vote
4
down vote

favorite









up vote
4
down vote

favorite











I want to watch a file until a bit of text appears



I found this answer: `tail -f` until text is seen



but when I tried it on ubuntu, it doesn't exit:



$ echo one > test.txt
$ echo two >> test.txt
$ echo three >> test.txt
$ echo four >> test.txt
$ cat test.txt | sed '/w/ q'
one
two
$


works as expected. however when I try to tail the file



$ tail -f test.txt | sed '/w/ q'
one
two


it never exits. tail does not stop even though the pipe is broken.



Does anybody know how to make tail exit when sed exits?







share|improve this question














I want to watch a file until a bit of text appears



I found this answer: `tail -f` until text is seen



but when I tried it on ubuntu, it doesn't exit:



$ echo one > test.txt
$ echo two >> test.txt
$ echo three >> test.txt
$ echo four >> test.txt
$ cat test.txt | sed '/w/ q'
one
two
$


works as expected. however when I try to tail the file



$ tail -f test.txt | sed '/w/ q'
one
two


it never exits. tail does not stop even though the pipe is broken.



Does anybody know how to make tail exit when sed exits?









share|improve this question













share|improve this question




share|improve this question








edited Mar 16 at 17:11









Stéphane Chazelas

280k53515847




280k53515847










asked Jan 10 at 16:40









Alex028502

1614




1614







  • 1




    Similar: unix.stackexchange.com/a/366806/22565
    – Stéphane Chazelas
    Jan 10 at 16:51










  • I don't think either of those are similar to this question. One is about writing your own program (in golang) that exits when the pipe is broken. This question is specifically about tail -f and asking why something in a previous answer doesn't work.
    – Alex028502
    Jan 10 at 17:15










  • The answers there explain why tail -f is not killed when sed exits, when the pipe is broken (because it doesn't write anything after) and how to work around it.
    – Stéphane Chazelas
    Jan 10 at 17:16










  • funny thing is what I am trying to do is an accepted answer here: unix.stackexchange.com/a/45943/158192
    – Alex028502
    Jan 10 at 17:20












  • 1




    Similar: unix.stackexchange.com/a/366806/22565
    – Stéphane Chazelas
    Jan 10 at 16:51










  • I don't think either of those are similar to this question. One is about writing your own program (in golang) that exits when the pipe is broken. This question is specifically about tail -f and asking why something in a previous answer doesn't work.
    – Alex028502
    Jan 10 at 17:15










  • The answers there explain why tail -f is not killed when sed exits, when the pipe is broken (because it doesn't write anything after) and how to work around it.
    – Stéphane Chazelas
    Jan 10 at 17:16










  • funny thing is what I am trying to do is an accepted answer here: unix.stackexchange.com/a/45943/158192
    – Alex028502
    Jan 10 at 17:20







1




1




Similar: unix.stackexchange.com/a/366806/22565
– Stéphane Chazelas
Jan 10 at 16:51




Similar: unix.stackexchange.com/a/366806/22565
– Stéphane Chazelas
Jan 10 at 16:51












I don't think either of those are similar to this question. One is about writing your own program (in golang) that exits when the pipe is broken. This question is specifically about tail -f and asking why something in a previous answer doesn't work.
– Alex028502
Jan 10 at 17:15




I don't think either of those are similar to this question. One is about writing your own program (in golang) that exits when the pipe is broken. This question is specifically about tail -f and asking why something in a previous answer doesn't work.
– Alex028502
Jan 10 at 17:15












The answers there explain why tail -f is not killed when sed exits, when the pipe is broken (because it doesn't write anything after) and how to work around it.
– Stéphane Chazelas
Jan 10 at 17:16




The answers there explain why tail -f is not killed when sed exits, when the pipe is broken (because it doesn't write anything after) and how to work around it.
– Stéphane Chazelas
Jan 10 at 17:16












funny thing is what I am trying to do is an accepted answer here: unix.stackexchange.com/a/45943/158192
– Alex028502
Jan 10 at 17:20




funny thing is what I am trying to do is an accepted answer here: unix.stackexchange.com/a/45943/158192
– Alex028502
Jan 10 at 17:20










1 Answer
1






active

oldest

votes

















up vote
6
down vote













It's the same things as in:



  • How to exit early on pipe close?

  • Grep slow to exit after finding match?

  • limit find output AND avoid signal 13

In:



cmd1 | cmd2


Your shell happens to wait until cmd1 terminates even after cmd2 has already terminated. That's not the case of all shells. Some like the Bourne or Korn shell don't for instance.



When cmd2 dies, the pipe on cmd1's stdout becomes broken, but that doesn't terminate cmd1 instantly.



cmd1 will terminate the next time it tries to write to that pipe. It will then receive a SIGPIPE whose default action is to terminate the process.



With cmd1 == tail -f file and cmd2 == sed /w/q, tail -f will read the last 10 lines of the file and write them to stdout (the pipe), typically in one chunk unless the lines are really big and sit there waiting for more text to be appended to file.



sed, which runs concurrently, will wait for input on its stdin, read it, process it line by line and quit if there's a line that contains w.



As soon (or possibly with a one-line delay with some sed implementation) as it finds that line, it exits, but at that time, tail has already written to the pipe all it had to WRITE, so it won't receive a SIGPIPE unless some additional text is added later on to the file (at which point it will do the fatal write()).



If you wanted cmd1 to terminate as soon as cmd2 terminates, you'd need something to kill it once cmd2 terminates. Like with:



sh -c 'echo "$$"; exec tail -f test.txt' | 
IFS= read pid
sed /w/q
kill -s PIPE "$pid"



Or with bash:



 sed /w/q; kill -s PIPE "$!"; < <(exec tail -f text.txt)





share|improve this answer






















  • +1! very useful for tailing a file until a message happens (such as waiting for a deploy to finish): awk 'print $0;/has finished in/exit' ; kill -s PIPE "$!" ; < <(exec tail -f /var/log/tomcat8/catalina.out)
    – David Dombrowsky
    Jul 6 at 20:04










Your Answer







StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "106"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);

else
createEditor();

);

function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
convertImagesToLinks: false,
noModals: false,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);



);








 

draft saved


draft discarded


















StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f416150%2fmake-tail-f-exit-on-a-broken-pipe%23new-answer', 'question_page');

);

Post as a guest






























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes








up vote
6
down vote













It's the same things as in:



  • How to exit early on pipe close?

  • Grep slow to exit after finding match?

  • limit find output AND avoid signal 13

In:



cmd1 | cmd2


Your shell happens to wait until cmd1 terminates even after cmd2 has already terminated. That's not the case of all shells. Some like the Bourne or Korn shell don't for instance.



When cmd2 dies, the pipe on cmd1's stdout becomes broken, but that doesn't terminate cmd1 instantly.



cmd1 will terminate the next time it tries to write to that pipe. It will then receive a SIGPIPE whose default action is to terminate the process.



With cmd1 == tail -f file and cmd2 == sed /w/q, tail -f will read the last 10 lines of the file and write them to stdout (the pipe), typically in one chunk unless the lines are really big and sit there waiting for more text to be appended to file.



sed, which runs concurrently, will wait for input on its stdin, read it, process it line by line and quit if there's a line that contains w.



As soon (or possibly with a one-line delay with some sed implementation) as it finds that line, it exits, but at that time, tail has already written to the pipe all it had to WRITE, so it won't receive a SIGPIPE unless some additional text is added later on to the file (at which point it will do the fatal write()).



If you wanted cmd1 to terminate as soon as cmd2 terminates, you'd need something to kill it once cmd2 terminates. Like with:



sh -c 'echo "$$"; exec tail -f test.txt' | 
IFS= read pid
sed /w/q
kill -s PIPE "$pid"



Or with bash:



 sed /w/q; kill -s PIPE "$!"; < <(exec tail -f text.txt)





share|improve this answer






















  • +1! very useful for tailing a file until a message happens (such as waiting for a deploy to finish): awk 'print $0;/has finished in/exit' ; kill -s PIPE "$!" ; < <(exec tail -f /var/log/tomcat8/catalina.out)
    – David Dombrowsky
    Jul 6 at 20:04














up vote
6
down vote













It's the same things as in:



  • How to exit early on pipe close?

  • Grep slow to exit after finding match?

  • limit find output AND avoid signal 13

In:



cmd1 | cmd2


Your shell happens to wait until cmd1 terminates even after cmd2 has already terminated. That's not the case of all shells. Some like the Bourne or Korn shell don't for instance.



When cmd2 dies, the pipe on cmd1's stdout becomes broken, but that doesn't terminate cmd1 instantly.



cmd1 will terminate the next time it tries to write to that pipe. It will then receive a SIGPIPE whose default action is to terminate the process.



With cmd1 == tail -f file and cmd2 == sed /w/q, tail -f will read the last 10 lines of the file and write them to stdout (the pipe), typically in one chunk unless the lines are really big and sit there waiting for more text to be appended to file.



sed, which runs concurrently, will wait for input on its stdin, read it, process it line by line and quit if there's a line that contains w.



As soon (or possibly with a one-line delay with some sed implementation) as it finds that line, it exits, but at that time, tail has already written to the pipe all it had to WRITE, so it won't receive a SIGPIPE unless some additional text is added later on to the file (at which point it will do the fatal write()).



If you wanted cmd1 to terminate as soon as cmd2 terminates, you'd need something to kill it once cmd2 terminates. Like with:



sh -c 'echo "$$"; exec tail -f test.txt' | 
IFS= read pid
sed /w/q
kill -s PIPE "$pid"



Or with bash:



 sed /w/q; kill -s PIPE "$!"; < <(exec tail -f text.txt)





share|improve this answer






















  • +1! very useful for tailing a file until a message happens (such as waiting for a deploy to finish): awk 'print $0;/has finished in/exit' ; kill -s PIPE "$!" ; < <(exec tail -f /var/log/tomcat8/catalina.out)
    – David Dombrowsky
    Jul 6 at 20:04












up vote
6
down vote










up vote
6
down vote









It's the same things as in:



  • How to exit early on pipe close?

  • Grep slow to exit after finding match?

  • limit find output AND avoid signal 13

In:



cmd1 | cmd2


Your shell happens to wait until cmd1 terminates even after cmd2 has already terminated. That's not the case of all shells. Some like the Bourne or Korn shell don't for instance.



When cmd2 dies, the pipe on cmd1's stdout becomes broken, but that doesn't terminate cmd1 instantly.



cmd1 will terminate the next time it tries to write to that pipe. It will then receive a SIGPIPE whose default action is to terminate the process.



With cmd1 == tail -f file and cmd2 == sed /w/q, tail -f will read the last 10 lines of the file and write them to stdout (the pipe), typically in one chunk unless the lines are really big and sit there waiting for more text to be appended to file.



sed, which runs concurrently, will wait for input on its stdin, read it, process it line by line and quit if there's a line that contains w.



As soon (or possibly with a one-line delay with some sed implementation) as it finds that line, it exits, but at that time, tail has already written to the pipe all it had to WRITE, so it won't receive a SIGPIPE unless some additional text is added later on to the file (at which point it will do the fatal write()).



If you wanted cmd1 to terminate as soon as cmd2 terminates, you'd need something to kill it once cmd2 terminates. Like with:



sh -c 'echo "$$"; exec tail -f test.txt' | 
IFS= read pid
sed /w/q
kill -s PIPE "$pid"



Or with bash:



 sed /w/q; kill -s PIPE "$!"; < <(exec tail -f text.txt)





share|improve this answer














It's the same things as in:



  • How to exit early on pipe close?

  • Grep slow to exit after finding match?

  • limit find output AND avoid signal 13

In:



cmd1 | cmd2


Your shell happens to wait until cmd1 terminates even after cmd2 has already terminated. That's not the case of all shells. Some like the Bourne or Korn shell don't for instance.



When cmd2 dies, the pipe on cmd1's stdout becomes broken, but that doesn't terminate cmd1 instantly.



cmd1 will terminate the next time it tries to write to that pipe. It will then receive a SIGPIPE whose default action is to terminate the process.



With cmd1 == tail -f file and cmd2 == sed /w/q, tail -f will read the last 10 lines of the file and write them to stdout (the pipe), typically in one chunk unless the lines are really big and sit there waiting for more text to be appended to file.



sed, which runs concurrently, will wait for input on its stdin, read it, process it line by line and quit if there's a line that contains w.



As soon (or possibly with a one-line delay with some sed implementation) as it finds that line, it exits, but at that time, tail has already written to the pipe all it had to WRITE, so it won't receive a SIGPIPE unless some additional text is added later on to the file (at which point it will do the fatal write()).



If you wanted cmd1 to terminate as soon as cmd2 terminates, you'd need something to kill it once cmd2 terminates. Like with:



sh -c 'echo "$$"; exec tail -f test.txt' | 
IFS= read pid
sed /w/q
kill -s PIPE "$pid"



Or with bash:



 sed /w/q; kill -s PIPE "$!"; < <(exec tail -f text.txt)






share|improve this answer














share|improve this answer



share|improve this answer








edited Mar 9 at 15:46

























answered Jan 10 at 17:31









Stéphane Chazelas

280k53515847




280k53515847











  • +1! very useful for tailing a file until a message happens (such as waiting for a deploy to finish): awk 'print $0;/has finished in/exit' ; kill -s PIPE "$!" ; < <(exec tail -f /var/log/tomcat8/catalina.out)
    – David Dombrowsky
    Jul 6 at 20:04
















  • +1! very useful for tailing a file until a message happens (such as waiting for a deploy to finish): awk 'print $0;/has finished in/exit' ; kill -s PIPE "$!" ; < <(exec tail -f /var/log/tomcat8/catalina.out)
    – David Dombrowsky
    Jul 6 at 20:04















+1! very useful for tailing a file until a message happens (such as waiting for a deploy to finish): awk 'print $0;/has finished in/exit' ; kill -s PIPE "$!" ; < <(exec tail -f /var/log/tomcat8/catalina.out)
– David Dombrowsky
Jul 6 at 20:04




+1! very useful for tailing a file until a message happens (such as waiting for a deploy to finish): awk 'print $0;/has finished in/exit' ; kill -s PIPE "$!" ; < <(exec tail -f /var/log/tomcat8/catalina.out)
– David Dombrowsky
Jul 6 at 20:04












 

draft saved


draft discarded


























 


draft saved


draft discarded














StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f416150%2fmake-tail-f-exit-on-a-broken-pipe%23new-answer', 'question_page');

);

Post as a guest













































































Popular posts from this blog

Peggy Mitchell

Palaiologos

The Forum (Inglewood, California)