2

Consider the following snippet of Bash script:

exec 3> >(sleep 1; echo "$BASHPID: here")
do-something-interesting
exec 3>&-
wait $!
echo "$BASHPID: there"

When executed, it produces:

a.sh: line 4: wait: pid 1001 is not a child of this shell
1000: there
1001: here

How can I modify the wait line so that it actually waits for the termination of 1001? In other words, I can I change the script so that the output becomes:

1001: here
1000: there
  • I'm surprised this actually works at all. My understanding of exec was that the current process calling exec is totally replaced by the new process thus lines after an exec is issued would not get executed. – mdpc Feb 18 '13 at 17:53
  • 2
    @mdpc: I'm not executing any command with exec, I'm just using it for output redirection. – user16538 Feb 18 '13 at 18:05
3

While bash sets $! for that background job started with exec 3> >(job), you can't wait for it or do any other things you'd be able to do with job & (like fg, bg or refer it by job number). ksh93 (where bash got that feature from) or zsh don't even set $! there.

You could do it the standard and portable way instead:

{
  {
     do-something-interesting
  } 3>&1 >&4 4>&- | { sleep 1; echo "$BASHPID: here"; } 4>&-
} 4>&1
echo "$BASHPID: there"

In zsh (and it's explicitly documented)

zmodload zsh/system
{
  do-something-interesting
} 3> >(sleep 1; echo $sysparams[pid]: here)
echo $sysparams[pid]: there

would also work, but not in ksh93 or bash.

  • Many thanks! Much more complicated than I'd have expected, but surely the only solution that does not involve changing the prospective. – user16538 Feb 20 '13 at 16:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.