开始后分离一个生成子进程


9

我以这种方式启动生成子进程:

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

process.unref()

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

当我开始该过程时,我需要使其保持连接状态,因为我想读取其输出。但是在关闭我的Node进程(父进程)之前,我想分离所有未完成的子进程以使其在后台运行,但是正如文档所述

使用分离选项启动长时间运行的进程时,除非父进程没有提供未连接到父进程的stdio配置,否则该进程将在父进程退出后不会在后台继续运行。

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

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

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

1
我有些困惑,为什么您期望能够读取独立于Node的进程的stdout / stderr。您可能需要捕获输出,因为该进程正在执行属于程序一部分的任务(只是并行运行),在这种情况下,Node 应该是父级。或者您正在启动一个真正独立的程序,在这种情况下,它的标准输出与您的Node程序无关,您应该让它们以对两个独立程序(例如数据库,文件监视器,API服务器)有意义的方式共享数据, 随你)。
Mike'Pomax'Kamermans

也许我还不够清楚,当我开始该过程时,我需要保持其附件状态,因为我想读取其输出。但是,在关闭Node进程(父进程)之前,我想分离所有未完成的子进程,以使其在后台运行。
Opsse

为什么不使用不同的进程/程序,并使用文件或其他方式在它们之间共享数据。
Ma'moun othman

这不是管道做什么?因此,您建议自己处理进程之间的通信?
Opsse

但是为什么要分开这个过程呢?它正在为程序的服务做某事,在这种情况下,您的程序应该等待直到完成,或者应该向进程发出信号,表明它的时间已到,需要完成它的工作,因为这将导致SIGKILL-基本:实际用例是什么?因为这听起来像是您想做某事的XY问题的主要候选人,并且您想到了做某事的方法,而您是在问这种做事的方法,而不是在问最初的问题
Mike 'Pomax'Kamermans

Answers:


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)

输出

开始主要
数据:开始子

获得数据:来自子项的问候
获得数据:来自子项的问候
获得数据:来自子项的问候
获得数据:来自子项的问候
断开子项的连接

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.