2014-06-30 53 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