Отключить дочерний процесс порождения после запуска - PullRequest
9 голосов
/ 08 января 2020

Я запускаю дочерний процесс порождения следующим образом:

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 Ответ

1 голос
/ 15 января 2020

После многих тестов я нашел, по крайней мере, один способ решения этой проблемы: уничтожить все каналы, прежде чем покинуть основной процесс.

Одна хитрость заключается в том, что дочерний процесс должен правильно обрабатывать трубы, разрушающие, если не может получить ошибку и закрыть в любом случае. В этом примере дочерний процесс узла, кажется, не имеет проблем с этим, но он может отличаться от других сценариев.

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)

output

Start Main
Получил данные: Start Child

Получил данные: hello from child
Получил данные: hello from child
Получил данные: привет от ребенка
Получил данные: привет от ребенка
Отключил ребенка

...