2014-06-30 4 views
5

Ich habe eine saubere Windows 8.1-Box mit lates node.js installiert (v0.10.29). Ich habe einen folgenden Testcode in zwei Dateien:Wie wird die node.js child_process.spawn() - Umleitung unter Windows korrekt verwendet?

a.js

var sub = require('child_process').spawn('node', ['b.js'], {silent: true}); 
sub.stdout.on("data", function (data) {console.log(data.toString());}); 

b.js

console.log("DEBUG 1"); 
console.log("DEBUG 2"); 
process.exit(); 

wenn ich a.ja über ausführen:

node a.js 

werde ich siehe "DEBUG 1" in der Konsolenausgabe - aber nicht "DEBUG 2". Wenn ich process.exit() entferne, werden beide Zeilen korrekt angezeigt. Dieses seltsame Verhalten tritt sowohl bei fork als auch bei spawn auf.

Irgendwelche Hinweise? Derselbe Code funktioniert ohne Probleme unter Linux.

aktualisieren 02.07.2014

scheint dies keine Wettlaufsituation zwischen Ausgang() ist und log(), da dies zu ändernden Sequenz reine gleichen Fehler erzeugen:

function print(text, next) { console.log(text); next(); } 
print("DEBUG 1", function() { 
    print("DEBUG 2", function() { 
    process.exit(); 
    }); 
}); 

aktualisieren 03.07. 2014

silent ist nicht in spawn() Dokumentation aufgeführt, aber es funktioniert. Es ist in fork Dokumentation aufgeführt, und wie ich zuvor erwähnt, ist dieses Problem gleich fork.

Es scheint, dass, wenn ich eine Verzögerung zwischen dem letzten Ausgang einführen und process.exit() alle korrekt funktioniert:

console.log("DEBUG 1"); 
console.log("DEBUG 2"); 
setTimeout(function() {process.exit();}, 10000); 

Aber das Problem manifestiert sich nur, wenn ich Rohr Ausgang zu übergeordneten Prozess: Wenn ich entfernen silent, sowohl Nachrichten werden auch ohne Verzögerung korrekt angezeigt, daher ist es höchstwahrscheinlich etwas falsch mit der Rohrkommunikation, nicht mit process.exit.

Weiteres Updates 03.07.2014

Es wurde spekuliert, dass Kommentare process.exit() beiden Prozesse beenden kann (beide a.ja und b.ja). Nein, es beendet nur gespawned/gabeled Prozess, ich überprüft dies durch Hinzufügen unendlich setTimeouta.js, es funktioniert glücklich, nachdem b.ja beendet ist, und immer noch keine "DEBUG 2" -Linie.

+1

Ich denke, das ist, weil node.js asynchron ist, und process.exit wird vor console.log Ende ausgeführt. Was ist, wenn Sie einen Rückruf versuchen? 'Funktion print (Text, Rückruf) {console.log (Text); callback();} print ("DEBUG1", Funktion() {print ("DEBUG2", Funktion() {process.exit();})}); ' – DrakaSAN

+0

@DrakaSAN Aktualisierte Frage, dasselbe Problem. – grigoryvp

+0

Jetzt ist das komisch. – DrakaSAN

Antwort

3

Dur bearbeiten für Klarheit:

Das Problem Sie Gesicht ist die gleichzeitige Veranstaltung zwischen console.log('DEBUG2') und process.end(), die zwei von ihnen sind (fast) zur gleichen Zeit genannt, aber process.end() haben eine höhere Priorität, und wenn Sie fertig sind , machen sub zu Fall hören stoppen, und so debug2 gedruckt werden stoppen:

In Ihrem Code:

a.js    |b.js 
start 
spawn    |start 
listen    |send('DEBUG1') 
get DEBUG1   |send('DEBUG2') 
start the event  |send KILL 
print DEBUG1  | 
get DEBUG2 
start the event 
get KILL 
kill b.js //DEBUG2 haven t been printed 

Nun, wenn Sie process.end verlangsamen:

b.js:

console.log('DEBUG1'); 
console.log('DEBUG2'); 
setTimeout(function() { 
    process.end(); 
}, 1000); 

a.js    |b.js 
start 
spawn    |start 
listen    |send('DEBUG1') 
get DEBUG1   |send('DEBUG2') 
start the event  |wait 
print DEBUG1  |wait 
get DEBUG2   |send KILL 
start the event 
print DEBUG2 
get KILL 
kill b.js 

Aber das ist lästig, und Sie können t wissen, wie viele "warten" da sein. Eine andere Lösung ist zu b.js von stdout erben zu machen, so dass es keine Veranstaltung zu machen:

a.js:

var sub = require('child_process').spawn('node', ['b.js'], {stdio:[process.stdin, process.stdout, process.stderr]}); 

a.js    |b.js 
start 
spawn    |start 
listen    |print DEBUG1 
        |print DEBUG2 
        |send KILL 
get KILL   | 
kill b.js 

nun kein Fehler anfälligen Code, aber Sie können t bekommen, was ist gedruckt in a.js. Ich denke, eine andere Lösung mit process.nextTick könnte funktionieren, aber ich weiß nicht, wie es funktionieren würde.

EDIT:

process.exit() Kill b.js, die das gewünschte Verhalten ist. a.js siehe data Ereignis Ende, und so eine leere Ereignisschleife, und so kill sich selbst:)

+0

Aktualisierte Frage, danke für die Forschung. Ich werde Ihre Antwort akzeptieren, wenn niemand erklären wird, was das Problem mit Pipe und process.exit() ist – grigoryvp

+0

Hinzugefügt einige Erläuterungen zu dem Problem. – DrakaSAN

+1

Dies ist für process.exit() nicht möglich, um das gesamte Programm zu beenden. "spawn" und "fork" starten einen separaten Prozess. Problem bleibt auch wenn ich endlosschleife in a.js stecke (es endet nie). So "process.exit()" endet eigentlich nur b.js :(. Aktualisierte Frage. – grigoryvp

Verwandte Themen