![如何通过管道将 fd 3 而不是 fd1 / fd2 传送给消费者](https://linux22.com/image/159595/%E5%A6%82%E4%BD%95%E9%80%9A%E8%BF%87%E7%AE%A1%E9%81%93%E5%B0%86%20fd%203%20%E8%80%8C%E4%B8%8D%E6%98%AF%20fd1%20%2F%20fd2%20%E4%BC%A0%E9%80%81%E7%BB%99%E6%B6%88%E8%B4%B9%E8%80%85.png)
我希望做这样的事情:
echo 'foo' >&3 3| cat
基本上,我想将 ' foo
'写入3
,然后仅将数据通过管道传输3
到cat
。但上面的方法不起作用,我得到:
bash: 3: Bad file descriptor
有人明白我想做什么吗?
对于 Node.js,我在这里有工作示例: https://gist.github.com/ORESoftware/0ad178f4512bbf956e54dd08f2412883
在 Node.js 要点中,这看起来很可靠,我们在命令行中执行以下操作:
node foo.js 3> some-file.sh
在节点进程中,我们正在写入3
文件描述符。
但我想知道如何使用管道而不是重定向来做到这一点。
像这样的东西:
node foo.js 3| cat
答案1
{ echo 'hello on fd3' >&3; } 3>&1 | cat
此处,echo
写入标准输出,但我们将其重定向到文件描述符 3(这对应于w
您在 Node 应用程序中执行的写入操作)。然后,我们将文件描述符 3 上的流输出到标准输出,以便能够通过管道将其发送到cat
。
同时丢弃标准输出:
{ echo 'hello on fd1'; echo 'hello on fd3' >&3; } 3>&1 1>/dev/null | cat
第一个echo
写入标准输出,第二个通过第一个示例中的重定向写入文件描述符 3。然后,文件描述符 3 被发送到标准输出(以便能够通过管道传送它),同时丢弃标准输出。
请注意,实际上并不需要1
in ,只是为了清楚起见而将其添加到此处。1>/dev/null
两条管道均hello on fd3
仅输出。
对于您的节点应用程序:
node foo.js 3>&1 | cat
或者,也丢弃标准输出,
node foo.js 3>&1 1>/dev/null | cat
或者,将标准输出发送到标准错误(默认为终端),
node foo.js 3>&1 1>&2 | cat
答案2
您可以在不进行进程替换并且不混合 fd 1 和 3 或 fd 1 和 2 的情况下完成此操作:
producer(){ echo to_out; echo >&2 to_err; echo >&3 to_fd3; }
consumer(){ sed "s/^/consumer $@: /" >/dev/tty; }
{ producer 3>&1 >&4 | consumer 3; } 4>&1 | consumer 1
to_err
consumer 1: to_out
consumer 3: to_fd3
{ producer 3>&1 >&4 | consumer 3; } 4>&1
to_out
to_err
consumer 3: to_fd3
答案3
不完全是通过进程替换的管道:
# cmd 3> >(cat)
或者,如果您可以混合 fd3 和 stdout 的输出,
# cmd 3>&1 | cat
答案4
所以对于 bash,这确实有效:
exec 3<> >(cat > temp.sh)
echo a >&3 # write to it
exec 3>&- # close fd 3.
但我想知道是否有一种不太冗长的方法可以做到这一点。并且无需进程替换,而是使用管道。