bash中输出捕获函数中{} 1>& 2和()1>& 2之间有什么区别

时间:2017-08-17 13:50:49

标签: bash function io-redirection

  1. {} - 在当前shell中执行while循环

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

    - > f() 永远不会返回!!!

  2. ()子shell

    中执行while循环
    function f {
        (
            while : ; do echo -n a; done  &
        ) 1>&2
    }
    
    a=$( f ); echo "returned"
    

    - > f() 返回!!!

  3. 为什么?他们中的一个会回来,而不是其他人?我不明白......

    我的分析:

    由于while - 循环行上的结尾&while循环将被分叉并开始自己的后台进程。此后台进程继承当前打开的fd列表。

    据我所知,由于while循环被封装,它继承了封装的fd列表。这就是

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

    按预期工作,l_file将包含“log”,e_file将包含“err”。

    因此,在{} 1>&2() 1>&2的情况下,bash会被告知不应该捕获stdout。

    为什么{} 2>&1案件会阻止它?

    • 一些评估顺序之谜?
    • 明确关闭stdout会有帮助吗?我不知道语法,但{} 1>&- 1>&2可能有帮助吗?

    GNU bash,版本4.3.30(1)-release(x86_64-pc-linux-gnu)

    修改

    根据目前为止的答案,我做了一些分析:

    11) {}

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

    - >显示after loop

    12) ()

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

    - >显示after loop

    - >显示returned

1 个答案:

答案 0 :(得分:6)

在输出关闭后打开FIFO时,命令替换不会返回。

重定向子shell时,该子shell不包含指向原始FD的文件描述符;它没有任何需要,因为重定向将由子shell终止隐式结束。

当您重定向某个块时,该块需要保留原始描述符的副本以在退出时恢复。因此,将有一个自动分配的文件描述符存储原始(预重定向)标准输出的副本,并且该FD的存在阻止FIFO使写端结束。

观察差异:

f() {
  ls -l "/proc/$BASHPID/fd"
}

out1=$( ( f; ) 2>&1; )
out2=$( { f; } 2>&1; )

在上文中,out1可能(剥离了不相关的字段)看起来像:

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

...而out2可能在类似条件下看起来像:

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

注意额外的FD 10,存储要恢复的备份。