gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-11-29 09:04:28 25 4
gpt4 key购买 nike

  1. with {} - 在当前 shell

    中执行 while 循环
    function f {
    {
    while : ; do echo -n a; done &
    } 1>&2
    }

    a=$( f ); echo "returned"

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

  2. ()subshel​​l

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

    a=$( f ); echo "returned"

    -> f() 返回!!!

为什么?其中一个会返回,而另一个不会?我不明白...


我的分析:

由于 while 循环行上的结束 &while 循环将被 fork 并启动其自己的后台进程。该后台进程继承了当前打开的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 都被告知它应该不会捕获任何标准输出。

为什么它在 {} 2>&1 情况下阻塞?

  • 一些评估顺序之谜?
  • 也许显式关闭标准输出会有帮助?不过,我不知道语法,也许 {} 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 的终止隐式结束。

当您重定向 block 时, block 需要保留原始描述符的副本以在退出时恢复。因此,将有一个自动分配的文件描述符存储原始(重定向前)stdout 的副本,并且此 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,存储要恢复的备份。

关于bash - bash 中输出捕获函数中的 {} 1>&2 和 () 1>&2 有什么区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45736992/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com