Home > Enterprise >  The execution order of process substitution in Bash
The execution order of process substitution in Bash

Time:10-16

I'm wondering if there is any rule of the execution order of process substitution in Bash.
Let's assume 3 codes below. The only differences are redirections and output file names.
Bash version is 5.0.17

codes

    # code1
    echo 'a_ ' | tee \
    >(sed 's/ /1/g' >> file-1) \
    >(sed 's/ /2/g' >> file-1) \
    >(sed 's/ /3/g' >> file-1) \
    >/dev/null
    
    # code2
    echo 'a_ ' | tee \
    >(sed 's/ /1/g' >  file-2) \
    >(sed 's/ /2/g' >> file-2) \
    >(sed 's/ /3/g' >> file-2) \
    >/dev/null
    
    # code3
    echo 'a_ ' | tee \
    >(sed 's/ /1/g' > file-3) \
    >(sed 's/ /2/g' > file-3) \
    >(sed 's/ /3/g' > file-3) \
    >/dev/null

result

head file*
==> file-1 <==
a_3
a_2
a_1

==> file-2 <==
a_1
a_2

==> file-3 <==
a_1

From the result, the execution order of process substituion seems to be:
At code1, 3→2→1
At code2, 3→1→2
At code3, (2→3 or 3→2)→1

I would like to know the rule of the order.
Any help?

CodePudding user response:

if there is any rule of the execution order of process substitution in Bash

No, there is no rule. There is no synchronization.

Bash spawns (fork exec) processes. These processes are completely separate, with no synchronization between them.

There is "order of spawning" - the left side of pipeline has to be started before the right side. But that is not sequencing of execution, only sequencing of "starting".

echo 'a_ ' | tee \
>(sed 's/ /1/g' > file-3) \
>(sed 's/ /2/g' > file-3) \
>(sed 's/ /3/g' > file-3) \
>/dev/null

Let's try to draw a tree of processes. Note that each "spawn" in this tree starts a new concurrent unsequenced process.

  • we start with our main bash process
    • spawn subshell for the right side of the pipeline
      • spawn subshell for the first >(...)
        • open truncate file file-3
        • spawn sed 's/ /1/g'
      • spawn subshell for the second >(...)
        • open truncate file file-3
        • spawn sed 's/ /1/g'
      • spawn subshell for the third >(...)
        • open truncate file file-3
        • spawn sed 's/ /1/g'
      • open truncate /dev/null
      • spawn tee
      • wait for tee to finish
      • wait for the third >(...) to finish execution
      • wait for the second >(...) to finish execution
      • wait for the first >(...) to finish execution
    • spawn subshell for the left side
      • spawn echo 'a_ '
      • wait for echo to finish
    • wait for left side subshell to finish
    • wait for right side subshell to finish

Each "branch" of the tree is executed concurrently, asynchronously. Only dots on the same level started from the same level happen sequentially. Moreover, parent processes are not synchronized with child processes - they only wait for the processes to finish the whole execution, not to finish a particular action.

Every single open truncate file file-3 is not sequenced with every other. One >(...) may finish the whole execution, the other may not even start. There is no sequencing.

  •  Tags:  
  • bash
  • Related