2

Given a | b, i'd like to kill b when a is finished. b is an interactive process, which doesn't terminates when a is finished (fzf in my case), and the whole a | b is executed in a $() subshell.

So far what i come up with was

echo $({ sleep 5 & a=$!; { wait $a; kill $b; } } | { fzf & b=$!; }) 

sleep represents a, and fzf represents b, the result in the example is used by echo, but in my case, it'd be an argument for ssh. It seems, that $b is not the PID of fzf, it's empty. As far as i understand, this shouldn't be the case, since i've used {}, and not (), so it's not executed in a subshell.

4
  • Maybe start a|b in the background and use pgrep to poll for a, then pkill to kill b as soon as a is gone. Commented Dec 10, 2018 at 22:19
  • @Jaleks I can't start a|b in the background, as b requires user interaction. Commented Dec 10, 2018 at 22:22
  • kk, sorry, thought It would be some GUI process, did not look up fzf. Maybe then start the killing process (with a time out at beginning) in background before executing a|b, e.g. (sleep 20; while pgrep myProcA; do sleep 1; done; pkill myProcB ) & Commented Dec 10, 2018 at 22:47
  • this probably should be a feature of fzf as it can react at the time of EOF on read of stdin; other methods would be way more complicated Commented Dec 11, 2018 at 15:16

1 Answer 1

0

You could do:

cmdA | perl -MIO::Poll -e ' $SIG{CHLD} = sub{wait; exit($? & 127 ? 128|($?&127) : $?>>8)}; $p = IO::Poll->new; $p->mask(STDIN, POLLHUP); if ($pid = fork) { $p->poll; kill "TERM", $pid; sleep 1; kill "KILL", $pid; pause; } else { exec @ARGV; }' -- cmdB 

However if cmdA outputs something just before exiting and whilst cmdB is not reading from the pipe at that very moment, chances are cmdB will be killed before it has had a chance to read it, let alone process it, so you might want to sleep a little after the pipe is closed and before killing it to give cmdB the time to read and process all of cmdA's output.

You could also decide not to kill it until the pipe has been drained which you can check in a loop with the FIONREAD ioctl() (and then maybe still give it extra time to process it).

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.