Todavía estoy tratando de comprender los puntos más finos de cómo puedo ejecutar un comando de shell de Linux o Windows y capturar la salida dentro de node.js; en última instancia, quiero hacer algo como esto ...
//pseudocode
output = run_command(cmd, args)
La pieza importante es que output
debe estar disponible para una variable (u objeto) de ámbito global. Probé la siguiente función, pero por alguna razón, me undefined
imprimen en la consola ...
function run_cmd(cmd, args, cb) {
var spawn = require('child_process').spawn
var child = spawn(cmd, args);
var me = this;
child.stdout.on('data', function(me, data) {
cb(me, data);
});
}
foo = new run_cmd('dir', ['/B'], function (me, data){me.stdout=data;});
console.log(foo.stdout); // yields "undefined" <------
Tengo problemas para entender dónde se rompe el código anterior ... un prototipo muy simple de ese modelo funciona ...
function try_this(cmd, cb) {
var me = this;
cb(me, cmd)
}
bar = new try_this('guacamole', function (me, cmd){me.output=cmd;})
console.log(bar.output); // yields "guacamole" <----
¿Puede alguien ayudarme a entender por qué try_this()
funciona y por qué run_cmd()
no? FWIW, necesito usar child_process.spawn
, porque child_process.exec
tiene un límite de búfer de 200 KB .
Resolución final
Acepto la respuesta de James White, pero este es el código exacto que funcionó para mí ...
function cmd_exec(cmd, args, cb_stdout, cb_end) {
var spawn = require('child_process').spawn,
child = spawn(cmd, args),
me = this;
me.exit = 0; // Send a cb to set 1 when cmd exits
me.stdout = "";
child.stdout.on('data', function (data) { cb_stdout(me, data) });
child.stdout.on('end', function () { cb_end(me) });
}
foo = new cmd_exec('netstat', ['-rn'],
function (me, data) {me.stdout += data.toString();},
function (me) {me.exit = 1;}
);
function log_console() {
console.log(foo.stdout);
}
setTimeout(
// wait 0.25 seconds and print the output
log_console,
250);
fuente
me.stdout = "";
encmd_exec()
para evitar la concatenaciónundefined
al principio del resultado.Respuestas:
Aquí hay tres problemas que deben solucionarse:
Primero es que espera un comportamiento sincrónico mientras usa stdout de forma asincrónica. Todas las llamadas en su
run_cmd
función son asincrónicas, por lo que generará el proceso hijo y regresará inmediatamente, independientemente de si algunos, todos o ninguno de los datos se han leído en la salida estándar. Como tal, cuando corresobtiene lo que sea que esté almacenado en foo.stdout en este momento, y no hay garantía de cuál será porque su proceso hijo aún podría estar ejecutándose.
El segundo es que stdout es un flujo legible , por lo que 1) el evento de datos se puede llamar varias veces y 2) la devolución de llamada recibe un búfer, no una cadena. Fácil de remediar; solo cambia
dentro
de modo que convertimos nuestro búfer en una cadena y agregamos esa cadena a nuestra variable stdout.
En tercer lugar , solo puede saber que ha recibido toda la salida cuando obtiene el evento 'final', lo que significa que necesitamos otro oyente y devolución de llamada:
Entonces, su resultado final es este:
fuente
this.stdout = "";
dentro de larun()
función, de lo contrario,console.log(foo.sdtout);
tendrá el prefijoundefined
.Una versión simplificada de la respuesta aceptada (tercer punto), simplemente funcionó para mí.
Uso:
fuente
child.stdout.on('close', (errCode) => { console.log(errCode) } )
Usé esto de manera más concisa:
funciona perfectamente. :)
fuente
sys.puts()
quedó obsoleto en 2011 (con Node.js v0.2.3). Deberías usarconsole.log()
en su lugar.La forma más sencilla es usar la biblioteca ShellJS ...
Ejemplo de EXEC:
ShellJs.org admite muchos comandos de shell comunes asignados como funciones de NodeJS, que incluyen:
fuente
shell.exec("foo.sh arg1 arg2 ... ")
. Sufoo.sh
guión puede hacer referencia a estos usando$1
,$2
... etc.Tuve un problema similar y terminé escribiendo una extensión de nodo para esto. Puedes consultar el repositorio de git. ¡Es de código abierto y gratuito y todas esas cosas buenas!
https://github.com/aponxi/npm-execxi
Las instrucciones de uso están en el archivo Léame . ¡No dude en hacer solicitudes de extracción o enviar problemas!
Pensé que valía la pena mencionarlo.
fuente
@ TonyO'Hagan es una
shelljs
respuesta completa, pero me gustaría resaltar la versión sincrónica de su respuesta:fuente
Una línea sincrónica:
require('child_process').execSync("echo 'hi'", function puts(error, stdout, stderr) { console.log(stdout) });
fuente
Hay un conflicto variable en su
run_cmd
función:Simplemente cámbielo a esto:
Para ver los errores, agregue siempre esto:
EDITAR Su código falla porque está intentando ejecutar lo
dir
que no se proporciona como un programa independiente separado. Es un comando encmd
proceso. Si quieres jugar con el sistema de archivos, usa nativerequire( 'fs' )
.Alternativamente (que no recomiendo) puede crear un archivo por lotes que luego puede ejecutar. Tenga en cuenta que el sistema operativo por defecto dispara archivos por lotes a través de
cmd
.fuente
C:\Windows\System32\netstat.exe
, esto todavía no produce resultados ... Mi sintaxis exacta fuefoo = new run_cmd('netstat.exe', ['-an'], function (me, data){me.stdout=data;});
... También probé la ruta completa sin éxito hasta ahoraEn realidad, no devuelve nada de su función run_cmd.
Funciona muy bien. :)
fuente
return
sea necesario siempre que establezca correctamente los atributos del objetoUna versión prometida de la respuesta más premiada:
Usar:
fuente