2015-06-03 15 views
5

Devo acquisire in uno stream personalizzato stream di un processo figlio generato.Node.js: Cattura STDOUT di `child_process.spawn`

child_process.spawn(command[, args][, options]) 

Per esempio,

var s = fs.createWriteStream('/tmp/test.txt'); 
child_process.spawn('ifconfig', [], {stdio: [null, s, null]}) 

Ora come faccio a leggere dalla /tmp/test.txt in tempo reale?

Sembra che child_process.spawn non utilizzi stream.Writable.prototype.writestream.Writable.prototype._write per la sua esecuzione.

Per esempio,

s.write = function() { console.log("this will never get printed"); }; 

Così come,

s.__proto__._write = function() { console.log("this will never get printed"); }; 

Sembra che utilizza descrittori di file under-the-hood di scrivere da child_process.spawn a un file.

Facendo questo non funziona:

var s2 = fs.createReadStream('/tmp/test.txt'); 
s2.on("data", function() { console.log("this will never get printed either"); }); 

Così, come posso ottenere le STDOUT contenuto di un processo figlio?

Quello che voglio ottenere è lo stream STDOUT di un processo figlio in un socket. Se fornisco la presa direttamente al parametro child_process.spawn come parametro stdio, chiude il socket quando termina, ma voglio tenerlo aperto.

Aggiornamento:

La soluzione è quella di utilizzare di default {stdio: ['pipe', 'pipe', 'pipe']} opzioni e ascoltare il creato .stdout del processo figlio.

var cmd = child_process.spaw('ifconfig'); 
cmd.stdout.on("data", (data) => { ... }); 

Ora, per alzare la posta, una domanda più impegnativa:

- Come si può leggere la STDOUT del processo figlio e conservano ancora i colori?

Ad esempio, se si inviano STDOUT a process.stdout in questo modo:

child_process.spawn('ifconfig', [], {stdio: [null, process.stdout, null]}); 

manterrà i colori e stampa a colori in uscita per la console, perché la proprietà .isTTY è impostato su trueprocess.stdout.

process.stdout.isTTY // true 

Ora, se si utilizza il default {stdio: ['pipe', 'pipe', 'pipe']}, i dati che leggerete sarà spogliato di colori della console. Come ottieni i colori?

Un modo per farlo sarebbe creare il proprio flusso personalizzato con fs.createWriteStream, perché child_process.spawn richiede che i flussi abbiano un descrittore di file.

Quindi impostare .isTTY di tale flusso su true, per preservare i colori.

E infine si avrebbe bisogno di catturare i dati che cosa child_process.spawn scrive a quella corrente, ma dal momento che child_process.spawn non usa né .prototype.write.prototype._write del torrente, si avrebbe bisogno di catturare il suo contenuto in qualche altro hacky modo.

Questo è probabilmente il motivo per child_process.spawn richiede che il flusso di avere un descrittore di file perché bypassa la chiamata .prototype.write e scrive direttamente sul file under-the-hood.

Qualche idea su come implementarlo?

risposta

4

È possibile farlo senza utilizzare un file temporaneo:

var process = child_process.spawn(command[, args][, options]); 
process.stdout.on('data', function (chunk) { 
    console.log(chunk); 
}); 
+0

funziona come un fascino! – Vad

+0

In questo modo si blocca il flusso di output tra le istruzioni o si perde un output in quell'intervallo? –

+0

@AsadSaeeduddin no, non blocca. – Magomogo

1

Ciao io sono sul mio cellulare ma cercherò di guidarvi come posso. Chiarirò quando vicino a un computer, se necessario

Quello che penso tu voglia leggere il stdout da uno spawn e fare qualcosa con i dati?

Si può dare la progenie di un nome di variabile invece di correre la funzione, ad esempio:

var child = spawn(); 

poi ascoltare l'output come:

child.stdout.on('data', function(data) { 
    console.log(data.toString()); 
}); 

Si potrebbe utilizzare che per scrivere i dati quindi a un file o qualsiasi altra cosa tu voglia fare con esso.

+0

Grazie, per la risposta veloce! – Vad

0

L'opzione stdio richiede i descrittori di file, non gli oggetti di flusso, quindi un modo per farlo è utilizzare fs.openSync() per creare un descrittore di file di output e noi.

Prendendo il tuo primo esempio, ma utilizzando fs.openSync():

var s = fs.openSync('/tmp/test.txt', 'w'); 
var p = child_process.spawn('ifconfig', [], {stdio: [process.stdin, s, process.stderr]}); 

È anche possibile impostare sia stdout e stderr allo stesso descrittore di file (per lo stesso effetto di bash di 2>&1).

Avrai bisogno di chiudere il file quando si è fatto, in modo da:

p.on('close', function(code) { 
    fs.closeSync(s); 
    // do something useful with the exit code ... 
}); 
Problemi correlati