Trennen Sie nach dem Start einen untergeordneten Spawn-Prozess

9

Ich starte einen Spawn-Child-Prozess folgendermaßen:

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

process.unref()

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

Wenn ich den Prozess starte, muss ich ihn angehängt halten, da ich seine Ausgabe lesen möchte. Aber kurz bevor ich meinen Knotenprozess (den übergeordneten Prozess) schließe, möchte ich alle nicht abgeschlossenen untergeordneten Prozesse trennen, damit sie im Hintergrund ausgeführt werden. In der Dokumentation heißt es jedoch:

Wenn Sie die getrennte Option verwenden, um einen Prozess mit langer Laufzeit zu starten, bleibt der Prozess nach dem Beenden des übergeordneten Elements nicht im Hintergrund ausgeführt, es sei denn, er verfügt über eine Standardkonfiguration, die nicht mit dem übergeordneten Prozess verbunden ist.

Aber mit der Option stdio: 'ignore'kann ich nicht lesen, stdoutwas ein Problem ist.

Ich habe zuvor versucht, die Pipes manuell zu schließen, um den übergeordneten Prozess zu schließen, aber es ist nicht erfolgreich:

// Trigger just before the main process end
process.stdin.end()
process.stderr.unpipe()
process.stdout.unpipe()
Opsse
quelle
1
Ich bin ein wenig verwirrt, warum Sie erwarten würden, stdout / stderr eines von Node unabhängigen Prozesses lesen zu können. Entweder müssen Sie die Ausgabe erfassen, da der Prozess Aufgaben ausführt, die Teil Ihres Programms sind (nur parallel ausgeführt werden). In diesem Fall sollte der Knoten der übergeordnete Knoten sein . oder Sie starten ein wirklich unabhängiges Programm. In diesem Fall ist die Standardausgabe nicht das Anliegen Ihres Node-Programms, und Sie sollten dafür sorgen, dass sie Daten auf eine Weise gemeinsam nutzen, die für zwei unabhängige Programme sinnvoll ist (z. B. eine Datenbank, einen Dateimonitor oder einen API-Server) , wie auch immer).
Mike 'Pomax' Kamermans
Vielleicht war mir nicht klar genug, wenn ich den Prozess starte, muss ich ihn anhängen, weil ich seine Ausgabe lesen möchte. Aber kurz bevor ich meinen Knotenprozess (den übergeordneten Prozess) schließe, möchte ich alle nicht abgeschlossenen untergeordneten Prozesse trennen, damit sie im Hintergrund ausgeführt werden.
Opsse
Warum nicht unterschiedliche Prozesse / Programme haben und Daten mithilfe einer Datei oder eines anderen Mittels zwischen ihnen austauschen?
Ma'moun othman
Es ist nicht was eine Pfeife macht? Sie schlagen also vor, die Kommunikation zwischen Prozessen selbst zu übernehmen?
Opsse
Aber warum sollten Sie den Prozess trennen? Entweder tut es etwas im Dienst Ihres Programms. In diesem Fall sollte Ihr Programm warten, bis es fertig ist, oder es sollte dem Prozess signalisieren, dass es nicht mehr zeitgemäß ist und das, was es tut, beenden muss, weil es im Begriff ist, SIGKILL'd zu erhalten - im Grunde : Was ist der eigentliche Anwendungsfall? Weil dies wie ein Hauptkandidat für ein XY-Problem klingt, bei dem Sie versuchen, etwas zu tun, und Sie sich einen Weg überlegt haben, dies zu tun, und Sie nach dieser Art fragen, Dinge zu tun, anstatt nach dem ursprünglichen Problem zu fragen
Mike 'Pomax' Kamermans

Antworten:

1

Nach vielen Tests habe ich mindestens einen Weg gefunden, um dieses Problem zu lösen: alle Rohre vorher zu zerstören, um den Hauptprozess zu verlassen.

Ein kniffliger Punkt ist, dass der untergeordnete Prozess die zerstörenden Pipes korrekt behandeln muss. Andernfalls kann ein Fehler auftreten und trotzdem geschlossen werden. In diesem Beispiel scheint der untergeordnete Knotenprozess kein Problem damit zu haben, aber es könnte bei anderen Szenarien anders sein.

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)

Ausgabe

Start Main
Got data: Start Child

Erhaltene Daten: Hallo vom Kind
Erhaltene Daten: Hallo vom Kind
Erhaltene Daten: Hallo vom Kind
Erhaltene Daten: Hallo vom Kind
Trennen Sie das Kind

Opsse
quelle