Use child_process.execSync pero mantenga la salida en la consola

160

Me gustaría usar el execSync método que se agregó en NodeJS 0.12 pero aún tengo el resultado en la ventana de la consola desde la que ejecuté el script Node.

Por ejemplo, si ejecuto un script NodeJS que tiene la siguiente línea, me gustaría ver la salida completa del comando rsync "live" dentro de la consola:

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

Entiendo que execSyncdevuelve la salida del comando y que podría imprimirlo en la consola después de la ejecución, pero de esta manera no tengo salida "en vivo" ...

suamikim
fuente

Respuestas:

324

Puede pasar el stdio del padre al proceso hijo si eso es lo que desea:

require('child_process').execSync(
    'rsync -avAXz --info=progress2 "/src" "/dest"',
    {stdio: 'inherit'}
);
gregers
fuente
3
Significa que el proceso secundario utilizará las secuencias stdin, stdout y stderr de los padres. Entonces, cuando el proceso secundario escribe a cualquiera de ellos, en realidad se escribirá directamente en la secuencia de los padres.
Gregers
77
Esta es una respuesta muy valiosa, ya que la documentación oficial no es realmente explícita sobre la sintaxis esperada.
chikamichi
49
En lugar de lo [0,1,2]que he usado 'inherit', que es equivalente [process.stdin, process.stdout, process.stderr]o [0,1,2]según los documentos
Kurt
10
Enlace correcto a la options.stdiodocumentación: nodejs.org/api/child_process.html#child_process_options_stdio
Shaun Lebron
2
@Booligoosh En lugar de simplemente agregar {stdio:'inherit'}, debe agregar .toString () y luego llamar a console.log manualmente con el resultado. Además, ni siquiera cumple con el requisito de preguntas de ver la salida del comando "en vivo". No creo que sea "mucho más simple", de hecho, no creo que sea más simple en absoluto.
Boileau
19

Simplemente puedes usar .toString() .

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

Esto se ha probado en Node v8.5.0, no estoy seguro de las versiones anteriores. De acuerdo con @etov , no funciona v6.3.1, no estoy seguro sobre el intermedio.

Ethan
fuente
3
Esto no funciona en caso de falla (código de estado! = 0) porque .execSync()arroja una Errorinstancia.
Álvaro González
No funciona para mí, es decir, la salida solo se escribe después de que finaliza el comando. ¿Esto se aplica a una versión específica? mi nodo -v: v6.3.1
etov
Considere actualizar la respuesta para tener en cuenta que es aplicable solo a ciertas versiones de nodos, esto lo haría más útil para otros
etov
1
Se ejecuta un voto negativo ya que ahora se está ejecutando la pregunta relacionada con la salida durante el comando.
Karfau
14

A menos que redirija stdout y stderr como sugiere la respuesta aceptada, esto no es posible con execSync o spawnSync. Sin redireccionar stdout y stderr, esos comandos solo devuelven stdout y stderr cuando se completa el comando.

Para hacer esto sin redirigir stdout y stderr, necesitará usar spawn para hacer esto, pero es bastante sencillo:

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);
});

Utilicé un comando ls que enumera archivos de forma recursiva para que pueda probarlo rápidamente. Spawn toma como primer argumento el nombre del ejecutable que está intentando ejecutar y, como segundo argumento, toma una matriz de cadenas que representan cada parámetro que desea pasar a ese ejecutable.

Sin embargo, si está configurado para usar execSync y no puede redirigir stdout o stderr por alguna razón, puede abrir otro terminal como xterm y pasarle un comando como este:

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

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

Esto le permitirá ver qué está haciendo su comando en la nueva terminal, pero aún tendrá la llamada síncrona.

Brian
fuente
2
El ejemplo que usa spawn puede ser correcto, pero la declaración inicial acerca de no estar a punto de usar execSync no es precisa. Ver respuesta de @gregers
AgDude