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

> with {} – 在当前 shell中执行while循环

function f {
    {
        while : ; do echo -n a; done  &
    } 1>&2
}

a=$( f ); echo "returned"

– > f()永远不会回来!
>()在子shell中执行while循环

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

a=$( f ); echo "returned"

– > f()将返回!!!

为什么?他们中的一个会回来,而不是另一个吗?我不明白……

我的分析:

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"

– >显示循环后

12)()

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

a=$( f ); echo "returned"

– >显示循环后

– >返回显示

解决方法

输出关闭时打开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,存储要恢复的备份.

相关文章

用的openwrt路由器,家里宽带申请了动态公网ip,为了方便把2...
#!/bin/bashcommand1&command2&wait从Shell脚本并行...
1.先查出MAMP下面集成的PHP版本cd/Applications/MAMP/bin/ph...
1、先输入locale-a,查看一下现在已安装的语言2、若不存在如...
BashPerlTclsyntaxdiff1.进制数表示Languagebinaryoctalhexa...
正常安装了k8s后,使用kubect工具后接的命令不能直接tab补全...