Shell:两个命令的 STDIN/STDOUT 相互管道

Shell:两个命令的 STDIN/STDOUT 相互管道

当我们使用 POSIX shell 运行它时,

$ cmd0 | cmd1

cmd0 的 STDOUT 通过管道传输到 cmd1 的 STDIN。

问:除此之外,我怎样才能将 cmd1 的 STDOUT 通过管道传输到 cmd0 的 STDIN?

是否强制使用从/到命名管道 (FIFO) 的重定向?我不太喜欢命名管道,因为它们占用了一些文件系统路径,而且我需要担心名称冲突。或者我是否必须通过 C、Python 或某些通用编程语言调用 pipeline(2)?

(cmd0 和 cmd1 都执行一些网络 I/O,因此它们不会永远互相阻塞。)

答案1

在具有双向管道的系统(非 Linux)上,您可以执行以下操作:

cmd0 <&1 | cmd1 >&0

在 Linux 上,您可以执行以下操作:

: | { cmd1 | cmd2; } > /dev/fd/0

这是可行的,因为在 Linux(和 Cygwin,但通常不是其他系统)上,/dev/fd/x管道x(命名或未命名)的 fd 的作用类似于命名管道,也就是说,在读取模式下打开它可以让您获得读取端并进入写入模式为您提供写作结束。

随着yash和它的x>>|y 管道重定向操作员:

{ cmd0 | cmd1; } >>|0

支持 coproc 的 shell:

  • 兹什:

       coproc cmd0
       cmd1 <&p >&p
    
  • 克什

       cmd0 |&
       cmd1 <&p >&p
    
  • bash4+

       coproc cmd0
       cmd1 <&"${COPROC[0]}" >&"${COPROC[1]}"
    

专用工具方法(无耻地从答案中复制这个非常相似的问题):

使用pipexec

pipexec [ A /path/to/cmd0 ] \
        [ B /path/to/cmd1 ] \
        '{A:1>B:0}' '{A:0>B:1}'

或者使用dpipe

dpipe cmd0 = cmd1

或者使用socat:

socat EXEC:cmd0 EXEC:cmd1,nofork                 # using socketpairs
socat EXEC:cmd0,commtype=pipes EXEC:cmd1,nofork  # using pipes

我不知道python,但这也相对容易完成perl

perl -e 'pipe STDOUT,STDIN; exec "cmd0 | cmd1"'

您始终也可以诉诸命名管道,但是为它们找到唯一的名称和一些安全目录来创建它们,限制对它们的访问(因此其他进程无法打开它们并干扰)以及之后的清理成为难以解决的额外问题克服可靠和便携。

无论如何,要小心死锁!

相关内容