2014-06-30 12 views
5

Ho una casella di Windows 8.1 pulita con leds node.js installato (v0.10.29). Ho un seguente codice di prova in due file:Come utilizzare correttamente node.js child_process.spawn() reindirizzamento su Windows?

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(); 

se eseguo a.ja via:

node a.js 

Lo farò vedi "DEBUG 1" nell'output della console - ma non "DEBUG 2". Se rimuovo process.exit(), entrambe le linee verranno visualizzate correttamente. Questo strano comportamento si verifica sia con fork e spawn.

Eventuali suggerimenti? Lo stesso codice funziona senza problemi su linux.

Aggiornamento 02.07.2014

Sembra che questa non è una condizione di competizione tra exit() e log(), in quanto la modifica di questa sequenza di pura produrre lo stesso errore:

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

Aggiornamento 03.07. 2014

silent non è elencato nella documentazione spawn(), ma funziona. È elencato nella documentazione fork e, come accennato in precedenza, questo problema è lo stesso con fork.

Sembra che se presento un ritardo tra l'ultima uscita e process.exit() tutto funziona correttamente:

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

Ma il problema si manifesta solo se i tubo output processo padre: se tolgo silent, sia i messaggi vengono visualizzati correttamente anche senza ritardo, quindi probabilmente è qualcosa di sbagliato nella comunicazione pipe, non con process.exit.

Ulteriori aggiornamenti 03.07.2014

è stato ipotizzato nei commenti che process.exit() può risolvere entrambi i processi (sia a.ja e b.ja). No, termina solo il processo generato/biforcuto, ho verificato questo aggiungendo infinito a a.js, funziona felicemente dopo che b.ja è terminato, e ancora nessuna riga "DEBUG 2".

+1

Penso che s perché node.js è asincrono, e process.exit viene eseguito prima di console.log fine. Cosa succede se provi in ​​una richiamata? 'funzione stampa (testo, callback) {console.log (testo); callback();} print ("DEBUG1", function() {print ("DEBUG2", function() {process.exit();})}); ' – DrakaSAN

+0

@DrakaSAN Domanda aggiornata, stesso problema. – grigoryvp

+0

Ora è strano. – DrakaSAN

risposta

3

Maggiore modificare per chiarezza:

Il problema che dovete affrontare è l'evento concorrente tra console.log('DEBUG2') e process.end(), due di loro sono chiamati (quasi) allo stesso tempo, ma process.end() hanno una priorità più alta, e quando è fatto , fare sub fermata ascoltare evento, e così fermare DEBUG2 da stampare:

Nel codice:

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 

Ora, se si rallenta process.end:

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 

Ma questo è fastidioso, e si può so quanti "attendere" non ci sarà. Un'altra soluzione è quella di rendere b.js ereditare di stdout, quindi non c'è nessun caso di fare:

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 

Ora, nessun codice soggetto ad errori, ma è possibile t ottenere ciò che è stampato in a.js. Penso che un'altra soluzione con process.nextTick potrebbe funzionare, ma non so come funzionerebbe.

EDIT:

process.exit() uccidere b.js, che è il comportamento previsto. a.js vedere l'evento data e così avere un ciclo di eventi vuoto, e quindi uccidersi:)

+0

Domanda aggiornata, grazie per la ricerca. Accetterò la tua risposta se nessuno spiegherà qual è il problema con pipe e process.exit() – grigoryvp

+0

Aggiunta una spiegazione sul problema. – DrakaSAN

+1

Questo non è possibile per process.exit() per terminare tutto il programma. "spawn" e "fork" iniziano il processo separato. Il problema rimane anche se metto un ciclo infinito in a.js (non finisce mai). Quindi "process.exit()" in realtà termina solo b.js :(. Domanda aggiornata – grigoryvp

Problemi correlati