【问题标题】:Node.js child processes and pipes - OSX vs UbuntuNode.js 子进程和管道 - OSX vs Ubuntu
【发布时间】:2014-08-20 20:10:43
【问题描述】:

我正在尝试让两个长时间运行的 进程进行通信 - 一个父进程和一个子进程 - 使用管道和 Node 的 模块。我希望孩子能够异步将数据发送回父母,我希望使用 来做到这一点。

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

家长:

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。

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

在 Ubuntu 上运行 parent 的输出如下:

$ 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

我尝试调查该节点使用 进行的内核调用,但无法理解输出。

【问题讨论】:

  • 两个进程都运行时ps aux | grep node的输出是什么?
  • @ChrisLacko 命令coffee parent.coffee 立即崩溃。在 OSX 上,它会打印它应该打印的内容,然后退出。我可以将运行时看到的错误添加到帖子中。

标签: node.js child-process pipe strace node.js ubuntu pipe child-process


【解决方案1】:

我自己想通了。错误在孩子身上。 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。

【讨论】:

    猜你喜欢
    • 2013-03-28
    • 2014-06-20
    • 2011-04-05
    • 1970-01-01
    • 2015-10-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-04
    相关资源
    最近更新 更多