2014-12-13 28 views
11

Devo eseguire un comando di shell interattiva all'interno di node.js. Consente la nostra shell interattiva sia $ python:Come eseguire il comando della shell interattiva all'interno di node.js?

var cp = require('child_process'); 
var pythonChildProcess = cp.spawn('python'); 

pythonChildProcess.stdout.on("data", function(data) { 
    console.log('data successfully written!', data); // never outputs anything 
}); 

pythonChildProcess.stdin.write('1 + 1'); 
pythonChildProcess.stdin.end(); 

Questo codice non visualizzerà nulla (ma stdout dovrebbe essere 2).

Ma se lo fosse, ci sarà un altro problema: come renderlo interattivo? Il processo termina quando chiamo pythonChildProcess.stdin.end();! Ma volevo solo finire stdin e scrivere il prossimo stdin!

UPD: Se potessi emulare la pressione del pulsante enter, sarei in grado di scrivere in modo interattivo sul processo. Ma aggiungere \n alla fine della stringa di input non aiuta.

+0

"per stdin fine e scrivere il prossimo stdin"? Puoi spiegare cosa intendi con questo? –

+0

@ E_net4, mi piacerebbe eseguire il comando '$ python', scrivere un input (ad esempio' 1 + 1'), "premere' enter' ", ottenere un output (' 2' nel caso), quindi scrivere un altro input ('10 + 10')," premi 'enter'" di nuovo, ottieni un altro output, poi scrivi un altro input e così via ... E tali sequenze di "input" ho chiamato "stdins" –

+0

quelli sono in realtà un singolo stream stdin, al quale si desidera inviare più righe di input. –

risposta

4

Innanzitutto, una delle cose che impedisce al nodo di interfacciarsi con altre shell interattive è che l'applicazione figlio deve mantenere il suo comportamento "interattivo", anche quando stdin non assomiglia ad un terminale. python sapeva che il suo stdin non era un terminale, quindi ha rifiutato di funzionare. Questo può essere sovrascritto aggiungendo il flag -i al comando python.

In secondo luogo, come ben menzionato nell'aggiornamento, si è dimenticato di scrivere un nuovo carattere di linea nello stream, quindi il programma si è comportato come se l'utente non avesse premuto Invio. Sì, questa è la strada giusta da percorrere, ma la mancanza di una modalità interattiva ti ha impedito di recuperare qualsiasi risultato.

Ecco qualcosa che è possibile fare per inviare più ingressi alla shell interattiva, pur essendo in grado di recuperare ogni risultato uno per uno. Questo codice sarà resistente alle lunghe uscite, accumulandole fino a quando non viene ricevuta una riga completa prima di eseguire un'altra istruzione. È possibile eseguire più istruzioni contemporaneamente, il che potrebbe essere preferibile se non dipendono dallo stato del processo genitore. Sentiti libero di sperimentare con altre strutture asincrone per raggiungere il tuo obiettivo.

var cp = require('child_process'); 
var childProcess = cp.spawn('python', ['-i']); 

childProcess.stdout.setEncoding('utf8') 

var k = 0; 
var data_line = ''; 

childProcess.stdout.on("data", function(data) { 
    data_line += data; 
    if (data_line[data_line.length-1] == '\n') { 
    // we've got new data (assuming each individual output ends with '\n') 
    var res = parseFloat(data_line); 
    data_line = ''; // reset the line of data 

    console.log('Result #', k, ': ', res); 

    k++; 
    // do something else now 
    if (k < 5) { 
     // double the previous result 
     childProcess.stdin.write('2 * + ' + res + '\n'); 
    } else { 
     // that's enough 
     childProcess.stdin.end(); 
    } 
    } 
}); 


childProcess.stdin.write('1 + 0\n'); 
3

Una versione tl; dr della risposta di @ E_net4, per chi capisce solo leggendo il codice. Per una spiegazione dettagliata, si prega di leggere la sua risposta. L'ha descritto bene.

var spawn = require('child_process').spawn 

var p = spawn('node',['-i']); 

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

p.stdin.write('1 + 0\n'); 

uscita:

> 
1 
Problemi correlati