0

I have this script verbatim:

#!/usr/bin/env bash


handle_json(){
  while read line; do
    cat <<EOF
{"@json-stdio":true,"value":{"mark":"$1","v":"$line"}}
EOF
    done;
}

( echo; echo; echo 'du results:'; exit 0 ) > >(handle_json foo);

echo "zoom"

when I execute it, I get this:

enter image description here

I have to manually kill it with ctrl-C since it won't exit on it's own.

All I am trying to do is send the stdout of the subshell to the bash function so it JSON stringify the output (don't worry about escaping special chars for now).

Anybody know why this script doesn't exit on it's own?

UPDATE:

this actually does what I want it to do:

( echo; echo; echo 'du results'; ) |  handle_json 'foo';

echo "zoom"

the above uses the pipe operator instead of redirection/process substition. I never expected the pipe operator to work here. Can someone explain why/how it works?

3
  • 2
    Are you sure it doesn't exit? It looks that bash is simply printing its prompt before the >(...) subshell has exited, which is to be expected with subshells which are run asynchronously. Press 'Enter' instead of '^C'.
    – user313992
    Dec 22, 2018 at 5:09
  • ... or put a sleep 1 at the end (just a debugging aid, not a good solution, as that's a race condition) to make sure the subshell finishes first. Then you'll see the prompt after 1s as expected.
    – derobert
    Dec 22, 2018 at 5:12
  • Don't post images of text. Just copy-paste the text instead, it makes it easier for others to read it.
    – ilkkachu
    Dec 22, 2018 at 9:04

1 Answer 1

3

As far as I can tell, your script did exit; it's just that the process substitution finished running and printing in the background after the outer shell printed its prompt.

A way to avoid this would be to simply pipe into your function instead of using > >(...):

( echo; echo; echo 'du results:'; exit 0 ) | handle_json foo

This works because, when writing cmd1 | cmd2, the two commands are started in parallel, with the standard output of cmd1 connected to the standard input of cmd2, and bash waits for both to have completed to consider the pipeline complete.

In contrast, cmd1 > >(cmd2) does nearly the same, except that bash does not wait for cmd2 to complete before going on with further commands (in this case, printing "zoom" and then exiting, letting the interactive bash print its prompt): if, by chance, cmd2 takes significantly more time to complete than cmd1, then the kind of surprising race condition you observed happens.

2
  • thanks, I updated the OP right after I saw this answer! why does this work and the redirection/process substitution behave so strangely? Dec 22, 2018 at 5:17
  • I will update my answer to address this additional question.
    – dhag
    Dec 22, 2018 at 5:32

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .