Usa child_process.execSync ma mantieni l'output nella console


160

Vorrei usare il execSyncmetodo che è stato aggiunto in NodeJS 0.12 ma ho ancora l'output nella finestra della console da cui ho eseguito lo script Node.

Ad esempio, se eseguo uno script NodeJS che ha la seguente riga, mi piacerebbe vedere l'output completo del comando rsync "live" all'interno della console:

require('child_process').execSync('rsync -avAXz --info=progress2 "/src" "/dest"');

Capisco che execSyncrestituisce l'output del comando e che potrei stamparlo sulla console dopo l'esecuzione, ma in questo modo non ho un output "live" ...

Risposte:


324

Puoi passare lo stdio del genitore al processo figlio se è quello che vuoi:

require('child_process').execSync(
    'rsync -avAXz --info=progress2 "/src" "/dest"',
    {stdio: 'inherit'}
);

3
Significa che il processo figlio utilizzerà i flussi stdin, stdout e stderr del genitore. Quindi, quando il processo figlio scrive su uno di essi, verrà effettivamente scritto direttamente nel flusso del genitore.
Gregers

7
Questa è una risposta molto preziosa, poiché la documentazione ufficiale non è realmente esplicita sulla sintassi prevista.
Chikamichi,

49
Invece di quello [0,1,2]che ho usato 'inherit', che è equivalente [process.stdin, process.stdout, process.stderr]o [0,1,2]come da documenti
Kurt

10
Link corretto alla options.stdiodocumentazione: nodejs.org/api/child_process.html#child_process_options_stdio
Shaun Lebron,

2
@Booligoosh Invece di aggiungere semplicemente {stdio:'inherit'}, devi aggiungere .toString () e quindi chiamare console.log manualmente con il risultato. Inoltre, non soddisfa nemmeno i requisiti delle domande per vedere l'output del comando "live". Non penso che sia "molto più semplice", in realtà non penso che sia più semplice.
Bollettino,

19

Puoi semplicemente usare .toString().

var result = require('child_process').execSync('rsync -avAXz --info=progress2 "/src" "/dest"').toString();
console.log(result);

Questo è stato testato su Node v8.5.0, non sono sicuro delle versioni precedenti. Secondo @etov , non funziona v6.3.1- non sono sicuro del mezzo.


3
Questo non funziona in caso di errore (codice stato! = 0) perché .execSync()genera Errorun'istanza.
Álvaro González,

Per me non funziona, ovvero l'output viene scritto solo al termine del comando. Questo vale per una versione specifica? my node -v: v6.3.1
etov,

Si prega di considerare l'aggiornamento della risposta per notare che è applicabile solo a determinate versioni del nodo - questo lo renderebbe più utile ad altri
etov,

1
Il downvote dal momento che ti è ora in relazione alla domanda riguardante l'output durante il comando viene eseguito.
karfau,

14

A meno che tu non reindirizzi stdout e stderr come suggerisce la risposta accettata, questo non è possibile con execSync o spawnSync. Senza reindirizzare stdout e stderr quei comandi restituiscono stdout e stderr solo quando il comando è completato.

Per fare questo senza reindirizzare stdout e stderr, dovrai usare spawn per farlo, ma è piuttosto semplice:

var spawn = require('child_process').spawn;

//kick off process of listing files
var child = spawn('ls', ['-l', '/']);

//spit stdout to screen
child.stdout.on('data', function (data) {   process.stdout.write(data.toString());  });

//spit stderr to screen
child.stderr.on('data', function (data) {   process.stdout.write(data.toString());  });

child.on('close', function (code) { 
    console.log("Finished with code " + code);
});

Ho usato un comando ls che elenca ricorsivamente i file in modo da poterlo testare rapidamente. Spawn prende come primo argomento il nome dell'eseguibile che stai cercando di eseguire e come secondo argomento prende una matrice di stringhe che rappresentano ogni parametro che vuoi passare a quell'eseguibile.

Tuttavia, se sei impostato sull'uso di execSync e non riesci a reindirizzare stdout o stderr per qualche motivo, puoi aprire un altro terminale come xterm e passare un comando in questo modo:

var execSync = require('child_process').execSync;

execSync("xterm -title RecursiveFileListing -e ls -latkR /");

Questo ti permetterà di vedere cosa sta facendo il tuo comando nel nuovo terminale ma avere comunque la chiamata sincrona.


2
L'esempio che utilizza spawn potrebbe essere corretto, ma l'istruzione di apertura sul fatto che non si sta per utilizzare execSync non è accurata. Vedi la risposta di @gregers
AgDude il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.