Від'єднайте процес нересту дитини після початку


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
Я трохи розгублений, чому ви очікуєте, що зможете прочитати stdout / stderr процесу, незалежного від Node. Або потрібно зафіксувати результат, оскільки процес виконує завдання, які є частиною вашої програми (просто працює паралельно), у цьому випадку Node повинен бути батьківським; або ви запускаєте справді незалежну програму, і в цьому випадку її стандартний вихід не стосується програми вашого вузла, і вам слід змусити їх обмінюватися даними таким чином, що має сенс для двох незалежних програм (наприклад, база даних, монітор файлів, сервер API , що б там не було).
Майк 'Pomax' Камерманс

Можливо, я був недостатньо зрозумілий, коли я запускаю процес, мені потрібно тримати його приєднаним, тому що я хочу прочитати його вихід. Але перед тим, як закрити свій Node-процес (батьківський), я хочу від'єднати всі незакінчені дочірні процеси, щоб тримати їх у фоновому режимі.
Опсе

Чому б не мати різних процесів / програми, і обмінюватися даними між ними, використовуючи файл або інше значення.
корінь

Це не те, що роблять труби? Тож ви пропонуєте власноруч спілкуватися між процесами?
Опсе

Але навіщо ви відмежуєте процес? Або це робить щось на користь вашої програми, і в такому випадку ваша програма повинна зачекати, поки вона закінчиться, або вона повинна сигналізувати про процес, що він закінчився і потрібно закінчити те, що він робить, тому що збирається отримати 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)

вихід

Почати Основні
дані: Початок дитини

Отримали дані: привіт від дитини
Отримали дані: привіт від дитини
Отримали дані: привіт від дитини
Отримали дані: привіт від дитини
Відключіть дитину

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.