我有一个简单的管道:
node foo.js | node bar.js
bar.js
将从 stdin 读取以获取数据foo.js
。
但我想做的是确保在foo.js 决定可以退出之前bar.js
获取最后一条消息。foo.js
本质上我想创建一个简单的请求/响应模式。
foo 写入 stdout --> bar 从 stdin 读取 --> bar 如何将消息发送回 foo?
有没有办法在管道中向后通信,或者永远不需要这样做?
答案1
在管道是双向的系统上(NetBSD、FreeBSD、SVR4 派生的 Unices(所有管道至少使用 STREAMS 的系统),但不是 Linux):
node foo.js <&1 | node bar.js >&0
除了已经提到的命名管道之外,您还可以使用套接字对:
perl -MSocket -e '
socketpair(A, B, AF_UNIX, SOCK_STREAM, PF_UNSPEC);
if (fork) {
open STDIN, "<&A";
open STDOUT, ">&B";
exec "node", "foo.js";
} else {
open STDIN, "<&B";
open STDOUT, ">&A";
exec "node", "bar.js";
}'
或者两个无名管道,例如使用Acoproc
。
和zsh
:
coproc node foo.js
node bar.js <&p >&p
ksh
:
node foo.js |&
node bar.js <&p >&p
bash
4+:
coproc node foo.js
node bar.js <&"${COPROC[0]}" >&"${COPROC[1]}"
或者使用yash
'sx>>|y
管道运算符:
{ node foo.js <&3 3<&- | node bar.js 3<&-; } >>|3
答案2
不。管道是一种单向通信通道。这就是为什么它被称为“管道”;即使你尝试,也无法将石油送回管道。
但是,如果 bar.js 也必须与 foo.js 通信,那么您有几个选择:
- 创建一个 unix 域套接字而不是管道,并分别启动两者
foo.js
(bar.js
即,不再将 foo.js 的输出通过管道传输到 bar.js 中)。我不知道如何从节点做到这一点,但本质上,unix 域套接字是一个网络套接字,它使用文件名而不是 IP 地址,并在内核内部工作。套接字用于双向通信,但需要比简单管道更多的设置(例如,侦听套接字可以与 bar.js 的多个实例通信)。您可能会在文件系统中找到 unix 域套接字,但这并不是绝对必要的(实际上 Linux 允许创建 unix 域套接字而不在文件系统上留下痕迹)。 - 用于
mkfifo
创建命名管道(或使用某些节点 API 来创建一个命名管道,如果存在的话;同样,我不知道节点)。然后,在 中foo.js
,打开该命名管道并从中读取。您的bar.js
脚本可以打开相同的命名管道并向其写入。
后者最容易过渡到,因为您仍然使用文件 I/O(打开命名管道需要在文件系统上打开文件),但仍然是单向的(尽管您有两个通道,每个方向一个) 。前者稍微干净一些,并且还允许您在必要时更轻松地将两个脚本之一迁移到不同的主机。
无论如何,如果您的脚本现在是双向通信的,那么为了清楚起见,我建议您将它们作为单独的进程启动,而不是让一个进程通过管道连接到另一个进程。恕我直言,他们现在是平等的伙伴,你的命令行应该显示这一点。但这只是一个细节,当然不是技术上必需的。
答案3
向后通信非常容易,尽管可能不推荐。当然,通过错误的沟通方式,您可能会在复杂的系统中得到一些非常好的/不愉快的反馈循环。
在 *nix 上,您可以使用 Node.js 执行此操作,如下所示:
// foo.js
process.stdout.write(process.pid);
// bar.js
process.stdin.resume().once('data', function(pid){
const writable = fs.createWriteStream(`/proc/${pid}/fd/0`);
writable.write('whatevs'); // write to stdin of foo.js
});
上面是简化的,但你明白了。理想情况下,您可以使用 JSON 对 stdio 消息进行编码。这是一个很好的库来做到这一点:https://github.com/ORESoftware/json-stdio
然而,问题是,在MacOS上,你没有能力使用/proc/<pid>
...上次我检查过,唯一的好方法是使用为这种情况mkfifo
创建一个唯一的fifo
,或者使用TCP或Unix域套接字。