{}
- 在当前shell中执行while循环
function f {
{
while : ; do echo -n a; done &
} 1>&2
}
a=$( f ); echo "returned"
- > f()
永远不会返回!!!
()
在子shell
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
案件会阻止它?
{} 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
答案 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,存储要恢复的备份。