2013-01-15 13 views
45

Ho uno script che emette "hi", dorme per un secondo, emette "hi", dorme per 1 secondo e così via e così via. Ora pensavo di essere in grado di affrontare questo problema con questo modello.Node.js genera il processo figlio e ottiene l'uscita terminale live

var spawn = require('child_process').spawn, 
temp = spawn('PATH TO SCRIPT WITH THE ABOVE BEHAVIOUR'); 

temp.stdout.pipe(process.stdout); 

Ora il problema è che l'attività deve essere completata affinché l'output sia visualizzato. Come lo sto capendo, questo è dovuto al fatto che il processo appena generato prende il controllo dell'esecuzione. Ovviamente node.js non supporta i thread quindi nessuna soluzione? La mia idea era di eseguire probabilmente due istanze, la prima per lo scopo specifico di creare l'attività e farla canalizzare l'output per processare la seconda istanza, considerando che questo può essere ottenuto.

risposta

52

Mi sto ancora bagnando i piedi con Node.js, ma ho qualche idea. innanzitutto, credo che sia necessario utilizzare execFile anziché spawn; execFile è per quando si ha il percorso di uno script, mentre spawn è per l'esecuzione di un comando noto che Node.js può risolvere contro il percorso del proprio sistema.

1. Provide a callback per elaborare l'uscita tamponata:

var child = require('child_process').execFile('path/to/script', [ 
    'arg1', 'arg2', 'arg3', 
], function(err, stdout, stderr) { 
    // Node.js will invoke this callback when the 
    console.log(stdout); 
}); 

2. Aggiungere un ascoltatore al processo figlio stdout stream (9thport.net)

var child = require('child_process').execFile('path/to/script', [ 
    'arg1', 'arg2', 'arg3' ]); 
// use event hooks to provide a callback to execute when data are available: 
child.stdout.on('data', function(data) { 
    console.log(data.toString()); 
}); 

Inoltre, sembra che ci siano opzioni in base alle quali è possibile scollegare il processo generato dal terminale di controllo del nodo, che gli consentirebbe di eseguire in modo asincrono. Non ho ancora testato questo, ma ci sono esempi in API docs che vanno qualcosa di simile:

child = require('child_process').execFile('path/to/script', [ 
    'arg1', 'arg2', 'arg3', 
], { 
    // detachment and ignored stdin are the key here: 
    detached: true, 
    stdio: [ 'ignore', 1, 2 ] 
}); 
// and unref() somehow disentangles the child's event loop from the parent's: 
child.unref(); 
child.stdout.on('data', function(data) { 
    console.log(data.toString()); 
}); 
+5

punti di bonus se si può spiegare come fare questo con exec() come ho bisogno di eseguire una shell cmd. – DynamicDan

+1

Puoi usare 'child.spawn()' con l'opzione 'shell' impostata su' true'. https://nodejs.org/api/child_process.html#child_process_child_process_spawn_command_args_options – CedX

+1

È inoltre possibile reindirizzare child.stdout direttamente a process.stdout con 'child.stdout.pipe (process.stdout);' – darkadept

1

bambino:

setInterval(function() { 
    process.stdout.write("hi"); 
}, 1000); // or however else you want to run a timer 

genitore:

require('child_process').fork('./childfile.js'); 
// fork'd children use the parent's stdio 
60

è molto più facile ora (2 anni dopo)!

Spawn restituisce un ChildObject, che sarà poi possibile ascoltare gli eventi con.Gli eventi sono:

  • Classe: processo figlio
    • Evento: 'Errore'
    • Evento: 'uscita'
    • Evento: 'stretta'
    • Evento: 'disconnessione'
    • Evento: "messaggio"

Ci sono anche una serie di oggetti dal ChildObject, essi sono:

  • Classe: processo figlio
    • child.stdin
    • child.stdout
    • child.stderr
    • bambino .stdio
    • child.pid
    • child.connected
    • child.kill ([segnale])
    • child.send (messaggio [, sendHandle] [, callback])
    • child.disconnect()

See maggiori informazioni qui su ChildObject: https://nodejs.org/api/child_process.html

Quindi, combinando tutto questo, si ottiene:

var spawn = require('child_process').spawn; 
var child = spawn('node ./commands/server.js'); 
child.stdout.on('data', function(data) { 
    console.log('stdout: ' + data); 
    //Here is where the output goes 
}); 
child.stderr.on('data', function(data) { 
    console.log('stderr: ' + data); 
    //Here is where the error output goes 
}); 
child.on('close', function(code) { 
    console.log('closing code: ' + code); 
    //Here you can get the exit code of the script 
}); 

Ed è così che puoi ottenere l'output con Node!

+4

+1, questo dovrebbe essere scelto come risposta giusta ora. Solo una nota, la variabile di dati nel callback arriva come oggetto Buffer. Puoi usare '' 'child.stdout.setEncoding ('utf8')' '' se vuoi che entrino le stringhe utf8. – Ashish

+0

Sto provando ad eseguire uno script python; è in esecuzione ma l'output non viene qui. 'var spawn = require ('child_process'). spawn; var child = spawn ('python', ['/my/path/to/python/file/my_python_file.py']); child.stdout.on ('data', funzione (dati) { console.log ('stdout:' + data); }); child.stderr.on ('data', funzione (dati) { console.log ('stderr:' + data); }); child.on ('close', function (code) { console.log ('codice di chiusura:' + codice); }); ' – ishandutta2007

10

Ho avuto un piccolo problema a ottenere l'output di registrazione dal comando "npm install" quando ho generato npm in un processo figlio. La registrazione in tempo reale delle dipendenze non è stata mostrata nella console genitore.

Il modo più semplice per fare ciò che il manifesto originale vuole sembra essere questo (NPM uova sulle finestre e accedere di tutto per console genitore):

var args = ['install']; 

var options = { 
    stdio: 'inherit' //feed all child process logging into parent process 
}; 

var childProcess = spawn('npm.cmd', args, options); 
childProcess.on('close', function(code) { 
    process.stdout.write('"npm install" finished with code ' + code + '\n'); 
}); 
0

ho trovato me stesso che richiede questa funzionalità abbastanza spesso che ho confezionato in una biblioteca chiamata std-pour. Dovrebbe consentire di eseguire un comando e visualizzare l'output in tempo reale. Per installare semplicemente:

npm install std-pour 

Poi è abbastanza semplice per eseguire un comando e vedere l'output in tempo reale:

const { pour } = require('std-pour'); 
pour('ping', ['8.8.8.8', '-c', '4']).then(code => console.log(`Error Code: ${code}`)); 

Si previsti basato in modo da poter catena più comandi. È persino compatibile con la firma delle funzioni con child_process.spawn, quindi dovrebbe essere una sostituzione in qualsiasi punto in cui lo si utilizza.

3

Qui è l'approccio più pulito che ho trovato:

require("child_process").spawn('bash', ['./script.sh'], { 
    cwd: process.cwd(), 
    detached: true, 
    stdio: "inherit" 
}); 
Problemi correlati