2014-06-30 52 views
7

我想要使用管道和节点的模块进行通信的父进程和子进程的两个长期运行进程。我希望孩子能够将数据异步发送回父母,并且我希望使用这样做。Node.js子进程和管道 - OSX vs Ubuntu

这里是我的代码的简化版本:

家长:

cp = require('child_process') 
es = require('event-stream') 

child = cp.spawn('coffee', ['child.coffee'], {stdio: [null, null, null, 'pipe']}) 

so = child.stdout.pipe(es.split()) 
p3 = child.stdio[3].pipe(es.split()) 

so.on 'data', (data) -> 
    console.log('stdout: ' + data) 

child.stderr.on 'data', (data) -> 
    console.log('stderr: ' + data); 

p3.on 'data', (data) -> 
    console.log('stdio3: ' + data); 

child.on 'close', (code) -> 
    console.log('child process exited with code ' + code) 

child.stdin.write "a message from your parent", "utf8" 

儿童:

fs = require('fs') 

p3 = fs.createWriteStream('/dev/fd/3', {encoding: 'utf8'}) 

process.stdin.on 'data', (data) -> 
    p3.write "hello #{process.pid} - #{data}\n", 'utf8' 
    process.stdout.write "world #{process.pid} - #{data}\n", 'utf8' 
    p3.end() 
    process.exit(0) 

process.stdin.on 'end', (data) -> 
    console.log "end of stdin" 
    p3.end() 
    process.exit(0) 

process.stdin.setEncoding('utf8') 
process.stdin.resume() 

代码工作在OSX 10.9,但未能在Ubuntu的盒子上运行。我已经尝试在Ubuntu 12.04和14.04下运行它。我正在运行Node 10.2x。

/dev/fd/在Ubuntu下象征性地链接到/proc/self/fd/所以我相信我的子进程正在打开正确的文件。

运行在Ubuntu的母公司的输出如下:

$ coffee parent.coffee 
stderr: 

stderr: events.js:72 

stderr:   throw er; // Unhandled 'error' event 

stderr: 
stderr: 
stderr: 
stderr: 
stderr:   ^

stderr: Error: UNKNOWN, open '/dev/fd/3' 




events.js:72 
     throw er; // Unhandled 'error' event 
      ^
Error: read ECONNRESET 
    at errnoException (net.js:901:11) 
    at Pipe.onread (net.js:556:19) 

我希望看到(并在OSX盒):

$ coffee parent.coffee 
stdio3: hello 21101 - a message from your parent 
stdout: world 21101 - a message from your parent 
stdio3: 
stdout: 
child process exited with code 0 

有可能与沟通孩子在Ubuntu上也使用命令行,所以在产生子进程时可能会在父级问题:

$ echo foo | coffee child.coffee 3>&1 
hello 3077 - foo 

world 3077 - foo 

我试图调查节点使用进行的内核调用,但无法获得输出的多少意义。

+0

'ps aux | grep node'当两个进程都在运行? – ctlacko

+0

@ChrisLacko命令'coffee parent.coffee'立即崩溃。在OSX上,它会打印它应该显示的内容,然后退出。我可以添加我在看帖子时看到的错误。 – Jacob

回答

4

我想出了自己。错误发生在孩子身上。 Ubuntu Linux操作系统是更严格的,当你要打开已打开的文件,该行:

p3 = fs.createWriteStream('/dev/fd/3', {encoding: 'utf8'}) 

被抛出一个错误。文件描述符3已经打开子运行时,所以代码应该如下所示:

儿童:

fs = require('fs') 

# parent opens the file descriptor 3 when spawning the child (and closes it when the child returns) 
fd3write = (s) -> 
    b = new Buffer(s) 
    fs.writeSync(3,b,0,b.length) 

process.stdin.on 'data', (data) -> 
    fd3write "p3 #{process.pid} - #{data}\n" 
    process.stdout.write "so #{process.pid} - #{data}\n", 'utf8' 
    process.exit(0) 

process.stdin.on 'end', (data) -> 
    console.log "end of stdin" 
    process.exit(0) 

process.stdin.setEncoding('utf8') 
process.stdin.resume() 

我希望这会有所帮助别人。

要使用管道而不是stdin将消息从父级发送到子级,可能使用此链接:child-process-multiple-file-descriptors

+0

您也可以将自己的答案标记为已接受。 :) – jgillich