问题描述
说我有
node foo.js | node bar.js
是否可以将foo的stdin的句柄传递给bar.js?
is there a way to pass a handle on foo's stdin to bar.js?
在极少数情况下,我想在管道中向后通信.
I have a rare case where I'd like to communicate backwards in the pipeline.
至少我知道我可以将node foo.js
的pid发送给node bar.js
.给定pid,在* nix上,我应该能够使用以下命令写入foo的标准输入:
At the least I know that I could send node bar.js
the pid of node foo.js
. Given that pid, on *nix, I should be able to write to foo's stdin using:
/proc/<pid>/fd/0
但是有没有办法在MacOS上做同样的事情?
but is there a way to do the same on MacOS?
推荐答案
所以有不同的方法.
方法1-IOCTL
这是受到
https://stackoverflow.com/a/36522620/2830850
因此,您创建具有以下内容的writevt.c
文件
So you create writevt.c
file with below content
/*
* 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
Now I created a simple foo.js
with below code
var stdin = process.openStdin();
stdin.addListener("data", function(d) {
console.log(process.env.NAME + " entered: [" +
d.toString().trim() + "]");
});
然后在终端中先运行tty
命令
And in a terminal run first the tty
command
$ tty
/dev/ttys019
现在运行如下代码
NAME=A node foo.js | NAME=B node foo.js
现在从另一个终端运行以下命令
Now from another terminal run the below command
./writevt /dev/ttys019 "FROM external command^M"
^M
在Mac上是CTRL+V
+ CTRL+ENTER
^M
here is CTRL+V
+ CTRL+ENTER
on Mac
从gif
可以看到,输入到达A的stdin
,然后A在stdout上打印,然后由B接收.因此,如果我修改如下代码
As you can see from the gif
the input reaches stdin
of A and then A prints on stdout and which is received by B then. So if I modify the code like below
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添加的
Note 1: ^M
was added using Vim inside the above code
注释2 :TTY位置已在其中进行了硬编码,但是您可以通过运行
Note 2: The TTY location has been hard coded in this but you can pass it through a environment variable by running
export TTY=`tty`
,然后在代码中使用process.env.TTY
.更新的结果是
And then using process.env.TTY
in the code. The updated results are
方法2-FIFO文件
使用这种方法,您首先要制作一个fifo文件
In this approach you make a fifo file first
$ mkfifo nodebridge
现在,您可以像下面那样更改代码
Now you change your code like below
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
这篇关于向下传递管道的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!