Отключить дочерний процесс порождения после запуска

9

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

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

process.unref()

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

Когда я запускаю процесс, мне нужно держать его подключенным, потому что я хочу прочитать его вывод. Но перед закрытием моего процесса Node (родительского) я хочу отсоединить все незавершенные дочерние процессы, чтобы они работали в фоновом режиме, но, как сказано в документации :

При использовании опции detached для запуска длительного процесса он не будет работать в фоновом режиме после выхода из родительского процесса, если ему не предоставлена ​​конфигурация stdio, которая не подключена к родительскому процессу.

Но с опцией stdio: 'ignore'я не могу прочитать, stdoutчто является проблемой.

Я пытался вручную закрыть каналы, прежде чем закрыть родительский процесс, но это не удалось:

// Trigger just before the main process end
process.stdin.end()
process.stderr.unpipe()
process.stdout.unpipe()
Opsse
источник
1
Я немного запутался, почему вы ожидаете, что сможете читать stdout / stderr процесса, независимого от Node. Либо вам нужно захватить вывод, потому что процесс выполняет задачи, которые являются частью вашей программы (просто работают параллельно), и в этом случае Node должен быть родительским; или вы запускаете действительно независимую программу, и в этом случае ее стандартный вывод не относится к вашей программе Node, и вы должны заставить их обмениваться данными способом, который имеет смысл для двух независимых программ (например, базы данных, файлового монитора, сервера API). , без разницы).
Майк 'Pomax' Камерманс
Возможно, я не был достаточно ясен, когда я запускаю процесс, мне нужно держать его подключенным, потому что я хочу прочитать его вывод. Но перед закрытием моего процесса Node (родительского) я хочу отсоединить все незавершенные дочерние процессы, чтобы они работали в фоновом режиме.
Опс
Почему бы не иметь разные процессы / программы, и обмениваться данными между ними, используя файл или каким-либо другим способом.
ROOT
Это не то, что делают трубы? Таким образом, вы предлагаете обрабатывать связь между процессами самостоятельно?
Опсс
Но зачем вам отрывать процесс? Либо она что-то делает для обслуживания вашей программы, и в этом случае ваша программа должна ждать, пока это не будет сделано, или она должна сигнализировать процессу, что он вышел из-под контроля и должен завершить свою работу, потому что она собирается получить SIGKILL'd - в основном : каков фактический вариант использования? Потому что это звучит как главный кандидат на проблему XY, когда вы пытаетесь что-то сделать, и вы думали о способе сделать это, и вы спрашиваете об этом способе делать вещи, а не спрашивать об исходной проблеме
Майк «Pomax» Камерманс

Ответы:

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)

вывод

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

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

Opsse
источник