Lepaskan proses anak spawn setelah memulai

9

Saya memulai proses menelurkan anak dengan cara ini:

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

process.unref()

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

Ketika saya memulai proses saya harus tetap terhubung karena saya ingin membaca hasilnya. Tetapi tepat sebelum menutup proses Node saya (orang tua) saya ingin melepaskan semua proses anak yang belum selesai agar mereka tetap berjalan di latar belakang, tetapi seperti yang dikatakan dalam dokumentasi :

Saat menggunakan opsi terlepas untuk memulai proses yang berjalan lama, proses tidak akan tetap berjalan di latar belakang setelah induk keluar kecuali jika disediakan dengan konfigurasi stdio yang tidak terhubung ke induk.

Tetapi dengan pilihan stdio: 'ignore'saya tidak bisa membaca stdoutyang merupakan masalah.

Saya mencoba untuk secara manual menutup pipa sebelum menutup proses induk tetapi tidak berhasil:

// Trigger just before the main process end
process.stdin.end()
process.stderr.unpipe()
process.stdout.unpipe()
Opsse
sumber
1
Saya agak bingung mengapa Anda berharap dapat membaca stdout / stderr dari suatu proses yang independen terhadap Node. Entah Anda perlu menangkap output, karena proses melakukan tugas-tugas yang merupakan bagian dari program Anda (hanya berjalan secara paralel) dalam hal ini Node harus menjadi induk; atau Anda memulai program yang benar-benar independen, dalam hal ini keluaran standarnya bukan urusan Program Node Anda dan Anda harus membuatnya berbagi data dengan cara yang masuk akal untuk dua program independen (misalnya database, monitor file, server API , Masa bodo).
Mike 'Pomax' Kamermans
Mungkin saya tidak cukup jelas, ketika saya memulai proses saya harus tetap terhubung karena saya ingin membaca hasilnya. Tetapi tepat sebelum menutup proses Node saya (orang tua) saya ingin melepaskan semua proses anak yang belum selesai agar mereka tetap berjalan di latar belakang.
Opsse
Mengapa tidak memiliki proses / program yang berbeda, dan berbagi data di antara mereka menggunakan file atau cara lain.
ROOT
Bukan apa yang dilakukan pipa? Jadi, Anda menyarankan untuk menangani komunikasi antar proses sendiri?
Opsse
Tetapi mengapa Anda melepaskan prosesnya? Entah itu melakukan sesuatu dalam pelayanan program Anda, dalam hal ini program Anda harus menunggu sampai selesai, atau harus menandakan proses bahwa itu keluar dari waktu dan perlu menyelesaikan apa yang dilakukannya karena akan mendapatkan SIGKILL - Pada dasarnya : apa use case yang sebenarnya? Karena ini kedengarannya seperti kandidat utama untuk masalah XY di mana Anda mencoba melakukan sesuatu, dan Anda memikirkan cara untuk melakukan itu, dan Anda bertanya tentang cara melakukan hal-hal alih-alih bertanya tentang masalah aslinya
Mike 'Pomax' Kamermans

Jawaban:

1

Setelah banyak tes saya menemukan setidaknya satu cara untuk menyelesaikan masalah ini: menghancurkan semua pipa sebelum meninggalkan proses utama.

Satu hal yang sulit adalah bahwa proses anak harus menangani dengan benar pipa-pipa yang menghancurkan, jika tidak bisa mendapatkan kesalahan dan tutup pula. Dalam contoh ini proses simpul anak tampaknya tidak memiliki masalah dengan ini tetapi bisa berbeda dengan skenario lainnya.

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)

keluaran

Mulai Utama,
dapatkan data: Mulai Anak

Mendapat data: hello from child
Mendapat data: hello from child
Mendapat data: hello from child
Mendapat data: hello from child
Putuskan sambungan anak

Opsse
sumber