如何通过管道将 fd 3 而不是 fd1 / fd2 传送给消费者

如何通过管道将 fd 3 而不是 fd1 / fd2 传送给消费者

我希望做这样的事情:

echo 'foo' >&3  3|  cat

基本上,我想将 ' foo'写入3,然后仅将数据通过管道传输3cat。但上面的方法不起作用,我得到:

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 被发送到标准输出(以便能够通过管道传送它),同时丢弃标准输出。

请注意,实际上并不需要1in ,只是为了清楚起见而将其添加到此处。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.

但我想知道是否有一种不太冗长的方法可以做到这一点。并且无需进程替换,而是使用管道。

相关内容