I am still trying to grasp the finer points of how I can run a linux or windows shell command and capture output within node.js; ultimately, I want to do something like this...
//pseudocode
output = run_command(cmd, args)
The important piece is that output
must be available to a globally scoped variable (or object). I tried the following function, but for some reason, I get undefined
printed to the console...
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" <------
I'm having trouble understanding where the code breaks above... a very simple prototype of that model works...
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" <----
Can someone help me understand why try_this()
works, and run_cmd()
does not? FWIW, I need to use child_process.spawn
, because child_process.exec
has a 200KB buffer limit.
I'm accepting James White's answer, but this is the exact code that worked for me...
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);
This question is related to
javascript
node.js
shell
There's a variable conflict in your run_cmd
function:
var me = this;
child.stdout.on('data', function(me, data) {
// me is overriden by function argument
cb(me, data);
});
Simply change it to this:
var me = this;
child.stdout.on('data', function(data) {
// One argument only!
cb(me, data);
});
In order to see errors always add this:
child.stderr.on('data', function(data) {
console.log( data );
});
EDIT You're code fails because you are trying to run dir
which is not provided as a separate standalone program. It is a command in cmd
process. If you want to play with filesystem use native require( 'fs' )
.
Alternatively ( which I do not recommend ) you can create a batch file which you can then run. Note that OS by default fires batch files via cmd
.
@TonyO'Hagan is comprehrensive shelljs
answer, but, I would like to highlight the synchronous version of his answer:
var shell = require('shelljs');
var output = shell.exec('netstat -rn', {silent:true}).output;
console.log(output);
I had a similar problem and I ended up writing a node extension for this. You can check out the git repository. It's open source and free and all that good stuff !
https://github.com/aponxi/npm-execxi
ExecXI is a node extension written in C++ to execute shell commands one by one, outputting the command's output to the console in real-time. Optional chained, and unchained ways are present; meaning that you can choose to stop the script after a command fails (chained), or you can continue as if nothing has happened !
Usage instructions are in the ReadMe file. Feel free to make pull requests or submit issues!
I thought it was worth to mention it.
require('child_process').execSync("echo 'hi'", function puts(error, stdout, stderr) { console.log(stdout) });
A simplified version of the accepted answer (third point), just worked for me.
function run_cmd(cmd, args, callBack ) {
var spawn = require('child_process').spawn;
var child = spawn(cmd, args);
var resp = "";
child.stdout.on('data', function (buffer) { resp += buffer.toString() });
child.stdout.on('end', function() { callBack (resp) });
} // ()
Usage:
run_cmd( "ls", ["-l"], function(text) { console.log (text) });
run_cmd( "hostname", [], function(text) { console.log (text) });
You're not actually returning anything from your run_cmd function.
function run_cmd(cmd, args, done) {
var spawn = require("child_process").spawn;
var child = spawn(cmd, args);
var result = { stdout: "" };
child.stdout.on("data", function (data) {
result.stdout += data;
});
child.stdout.on("end", function () {
done();
});
return result;
}
> foo = run_cmd("ls", ["-al"], function () { console.log("done!"); });
{ stdout: '' }
done!
> foo.stdout
'total 28520...'
Works just fine. :)
A promisified version of the most-awarded answer:
runCmd: (cmd, args) => {
return new Promise((resolve, reject) => {
var spawn = require('child_process').spawn
var child = spawn(cmd, args)
var resp = ''
child.stdout.on('data', function (buffer) { resp += buffer.toString() })
child.stdout.on('end', function () { resolve(resp) })
})
}
To use:
runCmd('ls').then(ret => console.log(ret))
Simplest way is to just use the ShellJS lib ...
$ npm install [-g] shelljs
EXEC Example:
require('shelljs/global');
// Sync call to exec()
var version = exec('node --version', {silent:true}).output;
// Async call to exec()
exec('netstat.exe -an', function(status, output) {
console.log('Exit status:', status);
console.log('Program output:', output);
});
ShellJs.org supports many common shell commands mapped as NodeJS functions including:
I used this more concisely :
var sys = require('sys')
var exec = require('child_process').exec;
function puts(error, stdout, stderr) { sys.puts(stdout) }
exec("ls -la", puts);
it works perfectly. :)
Source: Stackoverflow.com