【问题标题】:Child_process throw an Error: write EPIPEChild_process 抛出一个错误:写 EPIPE
【发布时间】:2016-05-10 12:05:32
【问题描述】:

我只是在练习一些关于 child_process @the link 的节点 js 代码 我的节点版本是 Windows 7 上的 V5.2.0。

// master.js
var cp=require("child_process");

var np=cp.fork("./console.js");               // line B

// block C
np.stdout.on("data",function(data){
   console.log("child process output:"+data);
});

np.stderr.on("data", function(err){
    console.log("child process output error:"+err);
});

np.on("close", function () {
    console.log("child process exit");
});

// end of block C



np.send({Hello:"world"});
np.on("message",function(msg){
    console.log("parent process got a msg:",msg);
});




// console.js

#!/usr/bin/env node

var aa=1;
console.log("The aa is :"+aa);


process.on("message", function (m) {
    console.log("child process got message:",m);
});

process.send({foo:"bar"});

1) 我运行上面的代码,我得到了错误:写 EPIPE。我用谷歌搜索,我没有找到任何有用的答案。我只是nodejs的新手,我按照官方文档进行了一些修改,然后示例代码失败了。我发现如果我将块 C 中的代码注释掉,示例代码就可以了。所以我想知道为什么代码会抛出错误,如果 np.stdout/np.stderr 监听“数据”?

$ The aa is :1
events.js:142
      throw er; // Unhandled 'error' event
      ^

Error: write EPIPE
    at exports._errnoException (util.js:856:11)
    at process.target._send (internal/child_process.js:607:18)
    at process.target.send (internal/child_process.js:508:19)
    at Object.<anonymous> (D:\Practice\..\console.js:
11:9)
    at Module._compile (module.js:399:26)
    at Object.Module._extensions..js (module.js:406:10)
    at Module.load (module.js:345:32)
    at Function.Module._load (module.js:302:12)
    at Function.Module.runMain (module.js:431:10)
    at startup (node.js:141:18)

2)我修改了master.js代码,运行如下代码:

var cp=require("child_process");

var np=cp.spawn("node", ["./console.js"]);

np.send({Hello:"world"});
np.on("message",function(msg){
    console.log("parent process got a msg:",msg);
});

它会抛出一个错误:

np.send({Hello:"world"});
   ^

TypeError: np.send is not a function

我重新访问node js official doc,我没有发现 spawn() 和 fork() 有很大不同。所以我想知道为什么 np.send 不是一个函数?

有没有官方文档没有提到的几点?

【问题讨论】:

    标签: javascript node.js child-process


    【解决方案1】:

    1/关于np.send not found方法

    child_process.send 方法在子进程被分叉或当其管道设置为 IPC 时可用

    分叉

    使用 child_process.fork() 时,您可以使用 child.send(message[, sendHandle][, callback]) 和消息是 由孩子的“消息”事件接收。

    ipc

    'ipc' - 创建用于传递消息/文件描述符的 IPC 通道 父母与孩子之间。一个 ChildProcess 最多可以有一个 IPC stdio 文件描述符。设置此选项可启用 ChildProcess.send() 方法。如果孩子将 JSON 消息写入此 文件描述符,那么这将触发 ChildProcess.on('message')。如果 child 是一个 Node.js 程序,则存在一个 IPC 通道 将启用 process.send() 和 process.on('message')。

    var child = spawn('cat', ['index.js', {stdio: 'ipc'});
    

    2/ 关于EPIPE

    EPIPE 表示您正在写入管道或套接字,而另一端有 终止连接。

    这就是说,我发现您的观察结果很可疑,因为如果您不打开管道,则不会填充孩子的 stdout && stderr && stdin 对象。因此它通常会引发错误,例如TypeError: Cannot read property 'on' of null

    然后我仔细检查了文档,发现 fork 非常特别,我注意到它们没有提供任何 stdio 选项。但是,据说它启用了send 方法。 我的理解是fork方法不会打开任何管道,只有send方法,on('message')机制可用。

    此代码有效,console.js 保持不变

    // master.js
    var cp=require("child_process");
    
    var np = cp.fork("./console.js");
    
    np.on("close", function () {
        console.log("child process exit");
    });
    
    
    np.send({Hello:"world"});
    np.on("message",function(msg){
        console.log("parent process got a msg:",msg);
    });
    

    要做类似的事情,但使用 spawn,我们应该利用 stdin 来编写,stdout 或 stderr 来监听,

    // master.js
    var cp=require("child_process");
    
    var np = cp.spawn(process.argv[0], ["./console.js"], {stdio: 'pipe'});
    
    np.stdout.on("data",function(data){
       console.log("child process output:"+data);
    });
    
    np.stderr.on("data", function(err){
        console.log("child process output error:"+err);
    });
    
    np.on("close", function () {
        console.log("child process exit");
    });
    
    np.stdin.end(JSON.stringify({Hello:"world"}))
    

    console.js

    #!/usr/bin/env node
    
    var aa=1;
    console.log("The aa is :"+aa);
    
    
    process.stdin.on("data", function (m) {
        console.log("child process got message:", m.toString());
    });
    
    process.stdout.write(JSON.stringify({foo:"bar"}))
    // process.send({foo:"bar"});
    

    就是这样。关于您提供的具体错误,我无法给您准确的答案。

    我希望这会有所帮助。

    【讨论】:

    • 我发现,我使用 spawn 而不是 fork,代码有效。 var np = cp.spawn('node', ["./child.js"], {stdio: ['inherit', 'inherit', 'inherit', 'ipc']});
    • 关于 EPIPE 错误,您能否给出更多解释?
    • 我可以试试,但不确定该说什么。你对什么感兴趣?
    • 本地计算机父子线程通信,为什么管道关闭?我搜索了一下,发现大部分主题都是关于 net/tcp 的,而不是关于本地的。有什么工具可以监控收盘吗?
    • 当孩子退出时,管道关闭。孩子也可以决定自己关闭管道,而无需退出。您的程序还可以在不杀死子进程的情况下关闭它的管道。
    猜你喜欢
    • 1970-01-01
    • 2014-12-26
    • 2016-04-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-17
    • 2012-09-02
    相关资源
    最近更新 更多