Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Quit from pipe in bash

For following bash statement:

tail -Fn0 /tmp/report | while [ 1 ]; do echo "pre"; exit; echo "past"; done

I got "pre", but didn't quit to the bash prompt, then if I input something into /tmp/report, I could quit from this script and get into bash prompt.

I think that's reasonable. the 'exit' make the 'while' statement quit, but the 'tail' still alive. If something input into /tmp/report, the 'tail' will output to pipe, then 'tail' will detect the pipe is close, then 'tail' quits.

  1. Am I right? If not, would anyone provide a correct interpretation?
  2. Is it possible to add anything into 'while' statement to quit from the whole pipe statement immediately? I know I could save the pid of tail into a temporary file, then read this file in the 'while', then kill the tail. Is there a simpler way?
  3. Let me enlarge my question. If use this tail|while in a script file, is it possible to fulfill following items simultaneously? a. If Ctrl-C is inputed or signal the main shell process, the main shell and various subshells and background processes spawned by the main shell will quit b. I could quit from tail|while only at a trigger case, and preserve other subprocesses keep running c. It's better not use temporary file or pipe file.
like image 934
Qiu Yangfan Avatar asked Dec 13 '13 02:12

Qiu Yangfan


1 Answers

You're correct. The while loop is executing in a subshell because its input is redirected, and exit just exits from that subshell.

If you're running bash 4.x, you may be able to achieve what you want with a coprocess.

coproc TAIL { tail -Fn0 /tmp/report.txt ;}
while [ 1 ]
do
    echo "pre"
    break
    echo "past"
done <&${TAIL[0]}
kill $TAIL_PID

http://www.gnu.org/software/bash/manual/html_node/Coprocesses.html

With older versions, you can use a background process writing to a named pipe:

pipe=/tmp/tail.$$
mkfifo $pipe
tail -Fn0 /tmp/report.txt >$pipe &
TAIL_PID=$!
while [ 1 ]
do
    echo "pre"
    break
    echo "past"
done <$pipe
kill $TAIL_PID
rm $pipe
like image 85
Barmar Avatar answered Sep 20 '22 00:09

Barmar