mravey
Tengo este script simple:
var exec = require('child_process').exec;
exec('coffee -cw my_file.coffee', function(error, stdout, stderr) {
console.log(stdout);
});
donde simplemente ejecuto un comando para compilar un archivo de script de café. Pero stdout nunca se muestra en la consola, porque el comando nunca termina (debido a la opción -w de café). Si ejecuto el comando directamente desde la consola, recibo un mensaje como este:
18:05:59 - compiled my_file.coffee
Mi pregunta es: ¿es posible mostrar estos mensajes con el exec de node.js? Si es así, ¿cómo? !
Pooria Azimi
no usar exec
. Usar spawn
que es un EventEmmiter
objeto. Entonces puedes escuchar stdout
/stderr
eventos (spawn.stdout.on('data',callback..)
) como suceden.
De la documentación de NodeJS:
var spawn = require('child_process').spawn,
ls = spawn('ls', ['-lh', '/usr']);
ls.stdout.on('data', function (data) {
console.log('stdout: ' + data.toString());
});
ls.stderr.on('data', function (data) {
console.log('stderr: ' + data.toString());
});
ls.on('exit', function (code) {
console.log('child process exited with code ' + code.toString());
});
exec
almacena en búfer la salida y generalmente la devuelve cuando el comando ha terminado de ejecutarse.
-
Muy lindo. FYI: El argumento de devolución de llamada de eventos stdout/stderr ‘datos’ es un búfer, así que llámelo con .toString()
– SergeL
9 mayo 2014 a las 14:01
-
Para aquellos de ustedes que no pueden hacer que spawn funcione en Windows, echen un vistazo a esta gran respuesta.
– tomekwi
27 de agosto de 2014 a las 8:33
-
exec también es un EventEmitter al menos en la última versión.
– Nikolái Tsenkov
27 de junio de 2015 a las 3:50
-
También tenga en cuenta que no se llamará a la devolución de llamada, siempre que el programa genere una nueva línea. Si desea recibir “eventos” del proceso secundario, este proceso debe vaciar el búfer (
flush(stdout);
en C) para disparar eventos en Node.js.– Julián F. Weinert
20 de marzo de 2016 a las 1:18
-
+1 en exec que también es un EventEmitter … pasé 2 horas refactorizando mi cadena en una matriz de argumentos (línea de comando ffmpeg muy larga y complicada) … solo para descubrir que realmente no necesitaba hacerlo.
– conversaciones muertas
04/04/2016 a las 13:34
natanael smith
exec
también devolverá un objeto ChildProcess que es un EventEmitter.
var exec = require('child_process').exec;
var coffeeProcess = exec('coffee -cw my_file.coffee');
coffeeProcess.stdout.on('data', function(data) {
console.log(data);
});
O pipe
la salida estándar del proceso hijo a la salida estándar principal.
coffeeProcess.stdout.pipe(process.stdout);
O heredar stdio usando spawn
spawn('coffee -cw my_file.coffee', { stdio: 'inherit' });
-
Parece que esto se puede simplificar simplemente usando
pipe
:coffeeProcess.stdout.pipe(process.stdout);
–Eric Freese
19/08/2015 a las 15:00
-
El comentario de @EricFreese es lo que estaba buscando, porque quería aprovechar la función de reemplazo de caracteres de stdout (transportador de aprovechamiento en un script de nodo)
– Lorem Ipsum
31/10/2016 a las 11:00
-
Más simple:
spawn(cmd, argv, { stdio: 'inherit' })
. Ver nodejs.org/api/child_process.html#child_process_options_stdio para diferentes ejemplos.-Morgan Touverey Quilling
30 de marzo de 2017 a las 14:39
-
+1 por la sugerencia de uso de @MorganTouvereyQuilling
spawn
constdio: 'inherit'
. Produce una salida más precisa queexec
y tuberíasstdout
/stderr
por ejemplo, cuando se muestra la información de progreso de ungit clone
.– Livven
18 de abril de 2017 a las 15:56
Livven
Ya hay varias respuestas, sin embargo, ninguna de ellas menciona la mejor (y más fácil) forma de hacerlo, que es usar spawn
y el { stdio: 'inherit' }
opción. Parece producir la salida más precisa, por ejemplo, al mostrar la información de progreso de un git clone
.
Simplemente haz esto:
var spawn = require('child_process').spawn;
spawn('coffee', ['-cw', 'my_file.coffee'], { stdio: 'inherit' });
Crédito a @MorganTouvereyQuilling por señalar esto en este comentario.
-
Descubrí que cuando el subproceso usa una salida formateada como texto en color,
stdio: "inherit"
conserva ese formato mientraschild.stdout.pipe(process.stdout)
no es.–Rikki Gibson
21/09/2017 a las 19:59
-
Esto conserva perfectamente la salida incluso en procesos con salida compleja como las barras de progreso en las instalaciones de npm. ¡Impresionante!
– Dave Koo
10 de junio de 2018 a las 18:17
-
¿Por qué esta no es la respuesta aceptada? ¡fue el único que funcionó para mí y son solo 2 f * líneas!
–Lincoln
23 de marzo de 2019 a las 20:56
-
Este consejo fue útil al ejecutar algunas aplicaciones de línea de comandos de Symfony que usan barras de progreso. Salud.
– Medio punto
16 de julio de 2019 a las 16:41
-
Esta debería ser la respuesta aceptada, lo único que preserva la representación de salida perfecta y es el mas sencillo? sí, por favor
– evnp
31 de marzo de 2020 a las 16:38
tyler liu
Inspirado por la respuesta de Nathanael Smith y el comentario de Eric Freese, podría ser tan simple como:
var exec = require('child_process').exec;
exec('coffee -cw my_file.coffee').stdout.pipe(process.stdout);
kevin teljeur
Solo me gustaría agregar ese pequeño problema con la salida de las cadenas de búfer de un proceso generado con console.log()
es que agrega líneas nuevas, que pueden distribuir la salida del proceso generado en líneas adicionales. Si tu salida stdout
o stderr
con process.stdout.write()
en lugar de console.log()
luego obtendrá la salida de la consola del proceso generado ‘tal cual’.
Vi esa solución aquí: Node.js: ¿imprimir en la consola sin una nueva línea final?
Espero que ayude a alguien que use la solución anterior (que es excelente para la salida en vivo, incluso si es de la documentación).
-
Para un uso de salida aún más preciso
spawn(command, args, { stdio: 'inherit' })
como lo sugiere @MorganTouvereyQuilling aquí stackoverflow.com/questions/10232192/…– Livven
18 de abril de 2017 a las 15:59
Quejas Generales
He encontrado útil agregar un script exec personalizado a mis utilidades que hacen esto.
utilidades.js
const { exec } = require('child_process')
module.exports.exec = (command) => {
const process = exec(command)
process.stdout.on('data', (data) => {
console.log('stdout: ' + data.toString())
})
process.stderr.on('data', (data) => {
console.log('stderr: ' + data.toString())
})
process.on('exit', (code) => {
console.log('child process exited with code ' + code.toString())
})
}
aplicación.js
const { exec } = require('./utilities.js')
exec('coffee -cw my_file.coffee')
-
Para un uso de salida aún más preciso
spawn(command, args, { stdio: 'inherit' })
como lo sugiere @MorganTouvereyQuilling aquí stackoverflow.com/questions/10232192/…– Livven
18 de abril de 2017 a las 15:59
Tongfa
Después de revisar todas las otras respuestas, terminé con esto:
function oldSchoolMakeBuild(cb) {
var makeProcess = exec('make -C ./oldSchoolMakeBuild',
function (error, stdout, stderr) {
stderr && console.error(stderr);
cb(error);
});
makeProcess.stdout.on('data', function(data) {
process.stdout.write('oldSchoolMakeBuild: '+ data);
});
}
A veces data
serán varias líneas, por lo que oldSchoolMakeBuild
el encabezado aparecerá una vez para varias líneas. Pero esto no me molestó lo suficiente como para cambiarlo.
Vine aquí buscando capturar stdout del ejecutable de Python. Tenga en cuenta que todo lo siguiente funcionará, pero debe ejecutar python con una opción “-u”, para salir sin búfer y, por lo tanto, tener actualizaciones en vivo.
– Andy
5 de noviembre de 2017 a las 18:36