说我有
node foo.js | node bar.js
有没有办法将 foo 的标准输入句柄传递给 bar.js?
在极少数情况下,我想在管道中进行反向通信。
至少我知道我可以发送 node bar.js
node foo.js
的 pid。鉴于该 pid,在 *nix 上,我应该能够使用以下方式写入 foo 的标准输入:
/proc/<pid>/fd/0
但是有没有办法在 MacOS 上做同样的事情?
最佳答案
所以有不同的方法。
方法 1 - IOCTL
这是灵感来自
https://stackoverflow.com/a/36522620/2830850
因此您创建了包含以下内容的writevt.c
文件
/*
* Mostly ripped off of console-tools' writevt.c
*/
#include <stdio.h>
#include <fcntl.h>
#include <termios.h>
#include <sys/ioctl.h>
#include <unistd.h>
char *progname;
static int usage() {
printf("Usage: %s ttydev text\n", progname);
return 2;
}
int main(int argc, char **argv) {
int fd, argi;
char *term = NULL;
char *text = NULL;
progname = argv[0];
argi = 1;
if (argi < argc)
term = argv[argi++];
else {
fprintf(stderr, "%s: no tty specified\n", progname);
return usage();
}
if (argi < argc)
text = argv[argi++];
else {
fprintf(stderr, "%s: no text specified\n", progname);
return usage();
}
if (argi != argc) {
fprintf(stderr, "%s: too many arguments\n", progname);
return usage();
}
fd = open(term, O_RDONLY);
if (fd < 0) {
perror(term);
fprintf(stderr, "%s: could not open tty\n", progname);
return 1;
}
while (*text) {
if (ioctl(fd, TIOCSTI, text)) {
perror("ioctl");
return 1;
}
text++;
}
return 0;
}
使用下面的代码编译它
gcc -o writevt writevt.c
然后给同一个添加root
权限
sudo chown root:wheel writevt
sudo chmod 4755 writevt
现在我用下面的代码创建了一个简单的foo.js
var stdin = process.openStdin();
stdin.addListener("data", function(d) {
console.log(process.env.NAME + " entered: [" +
d.toString().trim() + "]");
});
然后在终端中首先运行 tty
命令
$ tty
/dev/ttys019
现在运行如下代码
NAME=A node foo.js | NAME=B node foo.js
现在从另一个终端运行下面的命令
./writevt /dev/ttys019 "FROM external command^M"
^M
在 Mac 上是 CTRL+V
+ CTRL+ENTER
正如您从 gif
中看到的,输入到达 A 的 stdin
,然后 A 在标准输出上打印,然后由 B 接收。所以如果我像下面这样修改代码
var stdin = process.openStdin();
stdin.addListener("data", function(d) {
console.log(process.env.NAME + " entered: [" +
d.toString().trim() + "]");
});
if (process.env.NAME === "B") {
setInterval(function() {
require('child_process').exec(`./writevt /dev/ttys019 "Hello from B?
"`)
}, 1000)
}
注意 1:^M
是在上面的代码中使用 Vim 添加的
注意 2:TTY 位置已硬编码在此,但您可以通过运行
通过环境变量传递它export TTY=`tty`
然后在代码中使用process.env.TTY
。更新后的结果是
方法 2 - FIFO 文件
在这种方法中,您首先制作一个 fifo 文件
$ mkfifo nodebridge
现在你改变你的代码如下
var stdin = process.openStdin();
var fs = require("fs")
stdin.addListener("data", function(d) {
console.log(process.env.NAME + " entered: [" +
d.toString().trim() + "]");
});
if (process.env.NAME === "B") {
setInterval( () => {
require('child_process').exec('printf "Hello from B?\\n" > nodebridge')
}, 1000);
}
然后运行如下命令
NAME=A node foo.js < nodebridge | NAME=B node foo.js
关于node.js - 将句柄向下传递到管道,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47270986/