如何在两个程序之间建立双向管道?

如何在两个程序之间建立双向管道?

每个人都知道如何在两个程序之间建立单向管道(stdout第一个程序和stdin第二个程序的绑定)first | second:。

但是如何制作双向管道,即两个程序的交叉stdin绑定stdout?有没有简单的方法可以在 shell 中完成?

答案1

嗯,使用命名管道 ( ) 相当“简单” mkfifo。我将 easy 放在引号中,因为除非程序是为此设计的,否则很可能会出现死锁。

mkfifo fifo0 fifo1
( prog1 > fifo0 < fifo1 ) &
( prog2 > fifo1 < fifo0 ) &
( exec 30<fifo0 31<fifo1 )      # write can't open until there is a reader
                                # and vice versa if we did it the other way

现在,写入标准输出通常会涉及缓冲。因此,例如,如果两个程序都是:

#!/usr/bin/perl
use 5.010;
say 1;
print while (<>);

你会期望无限循环。但相反,双方都会陷入僵局。您需要添加$| = 1(或等效项)来关闭输出缓冲。造成僵局的原因是两个都程序正在等待标准输入上的某些内容,但它们没有看到它,因为它位于另一个程序的标准输出缓冲区中,并且尚未写入管道。

更新:结合 Stéphane Charzelas 和 Joost 的建议:

mkfifo fifo0 fifo1
prog1 > fifo0 < fifo1 &
prog2 < fifo0 > fifo1

做同样的事情,更短,更便携。

答案2

如果系统上的管道是双向的(至少在 Solaris 11 和某些 BSD 上如此,但在 Linux 上则不然):

cmd1 <&1 | cmd2 >&0

但要小心死锁。

另请注意,某些系统上的 ksh93 的某些版本使用管道 ( |)套接字对。套接字对是双向的,但 ksh93 显式关闭相反方向,因此即使在管道(由系统pipe(2)调用创建)是双向的系统上,上面的命令也不适用于这些 ksh93。

答案3

我不确定这是否是您想要做的:

nc -l -p 8096 -c second &
nc -c first 127.0.0.1 8096 &

首先在端口 8096 上打开一个侦听套接字,一旦建立连接,就会生成程序,second并将其stdin作为流输出和stdout流输入。

nc然后,启动第二个连接到侦听端口并生成程序的程序first,并将stdout其作为流输入和stdin流输出。

这并不完全是使用管道完成的,但它似乎可以满足您的需要。

由于这使用网络,因此可以在两台远程计算机上完成。这几乎就是 Web 服务器 ( second) 和 Web 浏览器 ( first) 的工作方式。

答案4

您可以使用管道执行器:

$ pipexec -- '[A' cmd1 ] '[B' cmd2 ] '{A:1>B:0}' '{B:1>A:0}'

相关内容