Cannot terminate a shell command with Ctrl+c

1.2k views Asked by At

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:

  1. use a tmp pid file

    ( tail -Fn0 ${monitor_file} & echo "$!" >${tail_pid} ) | \
    while IFS= read -r line; do 
        xxxx
    done 
    
  2. 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.

1

There are 1 answers

0
Gert van den Berg On BEST ANSWER

It works to trap the INT signal (sent by Ctrl-C) to kill the tail process.

$( r=$RANDOM; trap '{ kill $(cat /tmp/pid$r.pid);rm /tmp/pid$r.pid;exit; }' SIGINT EXIT; { ( tail -fn0 /tmp/a.txt & echo $! > /tmp/pid$r.pid  )| while read line; do echo $line; done } 3>&1 )

(I use a random value on the PID file name to at least mostly allow multiple instances to run)