【问题标题】:Detach a spawn child process after the start启动后分离一个子进程
【发布时间】:2020-04-26 00:52:23
【问题描述】:

我以这种方式启动一个子进程:

let process = spawn(apiPath, {
  detached: true
})

process.unref()

process.stdout.on('data', data => { /* do something */ })

当我开始这个过程时,我需要保持它连接,因为我想读取它的输出。但就在关闭我的节点进程(父进程)之前,我想分离所有未完成的子进程以保持它们在后台运行,但正如the documentation 所说:

当使用 detached 选项启动一个长时间运行的进程时,进程将不会在父进程退出后继续在后台运行,除非它提供了一个未连接到父进程的 stdio 配置。

但是使用stdio: 'ignore' 选项我无法读取stdout,这是一个问题。

在关闭父进程之前尝试手动关闭管道但不成功:

// Trigger just before the main process end
process.stdin.end()
process.stderr.unpipe()
process.stdout.unpipe()

【问题讨论】:

  • 我有点困惑,为什么您希望能够读取独立于 Node.js 的进程的 stdout/stderr。要么您需要捕获输出,因为该进程正在执行属于您程序的一部分的任务(只是并行运行),在这种情况下,节点 应该 是父节点;或者你正在启动一个真正独立的程序,在这种情况下,它的标准输出不是你的 Node 程序的关注点,你应该让它们以对两个独立程序有意义的方式共享数据(例如数据库、文件监视器、API 服务器,随便)。
  • 也许我不够清楚,当我开始该过程时,我需要将其保持连接,因为我想读取它的输出。但就在关闭我的节点进程(父进程)之前,我想分离所有未完成的子进程以保持它们在后台运行。
  • 为什么不使用不同的进程/程序,并使用文件或其他方式在它们之间共享数据。
  • 这不是管道的作用吗?所以你建议自己处理进程之间的通信?
  • 但是为什么你会分离进程?要么它正在为你的程序服务,在这种情况下你的程序应该等到它完成,或者它应该向进程发出信号它已经过时并且需要完成它正在做的事情,因为它即将获得 SIGKILL'd - 基本上: 实际用例是什么?因为这听起来像是XY problem 的主要候选人,您正在尝试做某事,并且您想到了一种方法来做到这一点,并且您正在询问这种做事方式而不是询问原始问题

标签: node.js multithreading spawn


【解决方案1】:

经过多次测试,我发现至少有一种方法可以解决这个问题:在离开主进程之前销毁所有管道。

一个棘手的问题是子进程必须正确处理管道破坏,否则它可能会出错并关闭。在此示例中,节点子进程似乎对此没有问题,但在其他情况下可能会有所不同。

main.js

const { spawn } = require('child_process')

console.log('Start Main')

let child = spawn('node', ['child.js'], { detached: true })
child.unref() // With this the main process end after fully disconnect the child

child.stdout.on('data', data => {
  console.log(`Got data : ${data}`)
})

// In real case should be triggered just before the end of the main process
setTimeout(() => {
  console.log('Disconnect the child')

  child.stderr.unpipe()
  child.stderr.destroy()
  child.stdout.unpipe()
  child.stdout.destroy()
  child.stdin.end()
  child.stdin.destroy()
}, 5000)

child.js

console.log('Start Child')

setInterval(function() {
   process.stdout.write('hello from child')
}, 1000)

输出

开始主
获取数据:启动子项

得到数据:来自孩子的你好
得到数据:来自孩子的你好
得到数据:来自孩子的你好
得到数据:来自孩子的你好
断开孩子的连接

【讨论】:

    猜你喜欢
    • 2015-02-15
    • 2015-11-19
    • 2014-09-21
    • 1970-01-01
    • 2015-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多