What is the difference between {} 1> & 2 and () 1> & 2 in the output capture function in bash

  • with {} - execute while loop in current shell

     function f { { while : ; do echo -na; done & } 1>&2 } a=$( f ); echo "returned" 

    -> f() will never return !!!

  • () execute a while loop in a subshell

     function f { ( while : ; do echo -na; done & ) 1>&2 } a=$( f ); echo "returned" 

    -> f() will return !!!

Why? will any of them return, but not the other? I do not understand...


My analysis:

The while will fork and start its own background process due to the & ending in the while -loop line. This background process inherits the current open list fd.

As far as I understand, since the while encapsulated, it inherits the fd encapsulation list. Here is how

 { echo log; echo err 1>&2; } 1>l_file 2>e_file 

works as expected, l_file will contain "log", e_file will contain "err".

So, in the case of {} 1>&2 or () 1>&2 , bash says that he should not expect stdout not to be written.

Why is it blocking the event {} 2>&1 ?

  • some sort of secret evaluation procedure?
  • Perhaps closing stdout would obviously help? I don’t know the syntax, although maybe {} 1>&- 1>&2 will help?

GNU bash version 4.3.30 (1) -release (x86_64-pc-linux-gnu)


EDIT

Based on the answers so far, I have done another analysis:

11) {}

 function f { { while : ; do echo -na; done & echo "after loop" } 1>&2 echo "end of function" } a=$( f ); echo "returned" 

-> after loop displayed

12) ()

 function f { ( while : ; do echo -na; done & echo "after loop" ) 1>&2 echo "end of function" } a=$( f ); echo "returned" 

-> after loop displayed

-> returned displayed

+5
source share
1 answer

Command substitution does not return until the FIFO opens when the output is closed.

When redirecting a subshell, this subshell does not contain a file descriptor pointing to the original FD; he does not need this, since the redirection will be implicitly completed by this end of the sub-hunger.

When a block is redirected, the block must save a copy of the original descriptor for recovery upon exit . Therefore, an automatically assigned file descriptor will be created that saves a copy of the pre-redirection stdout, and the existence of this FD prevents the end of the FIFO from closing.


Note the difference:

 f() { ls -l "/proc/$BASHPID/fd" } out1=$( ( f; ) 2>&1; ) out2=$( { f; } 2>&1; ) 

In the above example, out1 may (with nonzero fields) look like this:

 0 -> /dev/pts/0 1 -> pipe:[1146313] 2 -> pipe:[1146313] 255 -> /dev/pts/0 

... whereas out2 might look like this under similar conditions:

 0 -> /dev/pts/0 1 -> pipe:[1146327] 10 -> /dev/pts/0 2 -> pipe:[1146327] 255 -> /dev/pts/0 

Note the optional FD 10 that saves the backup to be restored.

+6
source

Source: https://habr.com/ru/post/1270967/


All Articles