无法使用 FD 5 和 6 重定向“coproc”流,但无法使用 FD 3 和 4。为什么?

无法使用 FD 5 和 6 重定向“coproc”流,但无法使用 FD 3 和 4。为什么?

在 OSX 上,尝试通过coproc将服务的 IO 流传递给客户端,将以 bash 脚本实现的服务公开给以 bash 脚本实现的客户端,并以 开始,我发现我可以使用变量 5 和 6,但不能使用 3 和 4 来保存流。我期望能够使用 3 或以上的任何数字。

例如,以下方法有效:

如果./capitalize服务

#!/usr/bin/env bash
while true; do 
    read line
    echo "${line^}"
done

并且./client

#!/usr/bin/env bash
lsof -p $$ | grep PIPE
echo $1 >&6
read line <&5
echo Result: "${line}"

我们检查 bash 版本,启动服务,并反映暴露的管道

$ bash --version
GNU bash, version 5.0.18(1)-release (x86_64-apple-darwin19.5.0)
$ coproc SVC { ./capitalize; }
$ echo ${SVC[@]}
63 60
$ lsof -p $$ | grep PIPE
bash    30833 Setup   60   PIPE 0xaafc4e53240e4cbe    16384                     ->0x1eca6ceb32d18709
bash    30833 Setup   63   PIPE 0x904d6242c4e8c148    16384                     ->0xe8caffae10f9dd84

然后执行

$ ./client "foo" 5< /dev/fd/${SVC[0]} 6> /dev/fd/${SVC[1]}
bash    31441 Setup    5   PIPE 0x904d6242c4e8c148    16384                     ->0xe8caffae10f9dd84
bash    31441 Setup    6   PIPE 0xaafc4e53240e4cbe    16384                     ->0x1eca6ceb32d18709
Result: Foo

然后事情就会按预期进行。foo已经大写为Foo,我们可以看到capitalize输出和输入流已经重新映射到client63 -> 560 -> 6

但是,如果我将文件描述符从 5 改为 3,将 6 改为 4,那么事情就会出乎意料地失败。失败的原因是描述符 3 和 4 没有传递给client

如果./client更新为

#!/usr/bin/env bash
lsof -p $$ | grep PIPE
echo $1 >&4
read line <&3
echo Result: "${line}"

然后执行

$ ./client "foo" 3< /dev/fd/${SVC[0]} 4> /dev/fd/${SVC[1]}
./client: line 3: 3: Bad file descriptor
./client: line 4: 4: Bad file descriptor
Result: 

由于文件描述符没有出现,因此没有结果!

那么为什么我可以使用5/6,但不能使用3/4? 是3/4保留的吗? 我怎么知道呢?


另外,如果我使用替代语法进行重定向,那么流就不会被重定向,即使我认为该语法在语义上是等效的。

因此改变这个

$ ./client "foo" 5< /dev/fd/${SVC[0]} 6> /dev/fd/${SVC[1]}

$ ./client "foo" 5<&${SVC[0]} 6>&${SVC[1]}

结果是

./client: line 3: 6: Bad file descriptor
./client: line 4: 5: Bad file descriptor
Result: 

这两种重定向语法不是5< /dev/fd/${SVC[0]}应该5<&${SVC[0]}等效吗?

提前致谢!

相关内容