每个人都知道如何在两个程序之间建立单向管道(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}'