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


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.