2014-06-30 8 views
7

Sto provando a ottenere due processi operativi da tempo per comunicare - un genitore e un figlio - utilizzando le pipe e il modulo del Node. Voglio che il bambino sia in grado di inviare i dati al genitore in modo asincrono, e speravo di usare un per farlo.Node.js figlio processi e pipe - OSX vs Ubuntu

Ecco una versione semplificata del mio codice:

principale:

cp = require('child_process') 
es = require('event-stream') 

child = cp.spawn('coffee', ['child.coffee'], {stdio: [null, null, null, 'pipe']}) 

so = child.stdout.pipe(es.split()) 
p3 = child.stdio[3].pipe(es.split()) 

so.on 'data', (data) -> 
    console.log('stdout: ' + data) 

child.stderr.on 'data', (data) -> 
    console.log('stderr: ' + data); 

p3.on 'data', (data) -> 
    console.log('stdio3: ' + data); 

child.on 'close', (code) -> 
    console.log('child process exited with code ' + code) 

child.stdin.write "a message from your parent", "utf8" 

bambini:

fs = require('fs') 

p3 = fs.createWriteStream('/dev/fd/3', {encoding: 'utf8'}) 

process.stdin.on 'data', (data) -> 
    p3.write "hello #{process.pid} - #{data}\n", 'utf8' 
    process.stdout.write "world #{process.pid} - #{data}\n", 'utf8' 
    p3.end() 
    process.exit(0) 

process.stdin.on 'end', (data) -> 
    console.log "end of stdin" 
    p3.end() 
    process.exit(0) 

process.stdin.setEncoding('utf8') 
process.stdin.resume() 

Il codice funziona su OSX 10.9, ma non riesce a funzionare su una casella di Ubuntu. Ho provato a farlo funzionare con Ubuntu 12.04 e 14.04. Sto facendo funzionare il nodo 10.2x.

/dev/fd/ sotto Ubuntu è collegato simbolicamente a /proc/self/fd/ quindi credo che il processo figlio apre il file giusto.

L'uscita dalla esecuzione del genitore su Ubuntu è la seguente:

$ coffee parent.coffee 
stderr: 

stderr: events.js:72 

stderr:   throw er; // Unhandled 'error' event 

stderr: 
stderr: 
stderr: 
stderr: 
stderr:   ^

stderr: Error: UNKNOWN, open '/dev/fd/3' 




events.js:72 
     throw er; // Unhandled 'error' event 
      ^
Error: read ECONNRESET 
    at errnoException (net.js:901:11) 
    at Pipe.onread (net.js:556:19) 

mi aspetterei di vedere (e da fare su una casella OSX):

$ coffee parent.coffee 
stdio3: hello 21101 - a message from your parent 
stdout: world 21101 - a message from your parent 
stdio3: 
stdout: 
child process exited with code 0 

E 'possibile comunicare con il bambino utilizza la riga di comando anche su Ubuntu, quindi il problema è probabile nel genitore quando si genera il processo figlio:

$ echo foo | coffee child.coffee 3>&1 
hello 3077 - foo 

world 3077 - foo 

Ho cercato di indagare le chiamate del kernel che il nodo fa usando , ma non poteva dare molto senso all'output.

+0

Qual è l'output di 'ps aux | nodo grep' quando entrambi i processi sono in esecuzione? – ctlacko

+0

@ChrisLacko Il comando 'coffee parent.coffee' si arresta immediatamente. Su OSX stampa ciò che deve e poi esce. Posso aggiungere gli errori che vedo quando lo eseguo sul post. – Jacob

risposta

4

L'ho capito da solo. L'errore era nel bambino. Ubuntu Linux è più severo quando si tratta di aprire file che sono già aperti, la linea:

p3 = fs.createWriteStream('/dev/fd/3', {encoding: 'utf8'}) 

stato gettando un errore. Il descrittore di file 3 è già aperto quando il bambino viene eseguito, quindi il codice dovrebbe apparire come segue:

bambini:

fs = require('fs') 

# parent opens the file descriptor 3 when spawning the child (and closes it when the child returns) 
fd3write = (s) -> 
    b = new Buffer(s) 
    fs.writeSync(3,b,0,b.length) 

process.stdin.on 'data', (data) -> 
    fd3write "p3 #{process.pid} - #{data}\n" 
    process.stdout.write "so #{process.pid} - #{data}\n", 'utf8' 
    process.exit(0) 

process.stdin.on 'end', (data) -> 
    console.log "end of stdin" 
    process.exit(0) 

process.stdin.setEncoding('utf8') 
process.stdin.resume() 

Spero che questo sarà di aiuto a qualcun altro.

Per utilizzare un pipe anziché stdin per inviare messaggi dal genitore al figlio questo collegamento potrebbe essere utile: child-process-multiple-file-descriptors.

+0

Puoi anche contrassegnare le tue risposte come accettate. :) – jgillich