Would someone please tell me why below bash
statement cannot be terminated by Ctrl+c properly?
$( { ( tail -fn0 /tmp/a.txt & )| while read line; do echo $line; done } 3>&1 )
I run this statement, then two bash
processes and one tail
process are launched(got from ps auxf
), then input Ctrl+c, and it won't quit to the bash
prompt, at this moment, I see the two bash
processes stopped, while the tail
is still running, then I input something into /tmp/a.txt
, then we could get into bash prompt.
What I want is, input Ctrl+c, then just quit into bash
prompt without any relevant process left.
It will be more appreciative that someone explains the exact process of this statement, like a pipe causes the bash fork, something redirect to somewhere, etc.
Updated at Oct 9 2014:
Here provide some update in case it's useful to you. My adopt solution is alike with 2 factors:
use a tmp pid file
( tail -Fn0 ${monitor_file} & echo "$!" >${tail_pid} ) | \ while IFS= read -r line; do xxxx done
use trap like:
trap "rm ${tail_pid} 2>/dev/null; kill 0 2>/dev/null; exit;" INT TERM
to kill relevant processes and remove remain files.
Please note, this kill 0 2
is bash specific, and 0 means all processes in the current process group.
This solution used a tmp pid file, while I still expect other solution without tmp pid file.
$(...)
? That's for command substitution. – Collencollenchymabash
waits (or can wait) for all children (so the statuses are collected in thePIPESTATUS
array), which means that the 'pipeline' doesn't end until all processes are terminated, andtail -f
does not terminate until it gets a SIGPIPE signal after writing something to the pipe. – Proteintrap
(for the interrupt signal) to kill tail, You might need to save the PID, which can be tricky... (pgrep -f "tail -fn0 /tmp/a.txt"
would work, but will give problems if multiple instances are running...) – Touching