本文介绍了向下传递管道的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

说我有

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

这篇关于向下传递管道的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-24 07:42