Javascript node.js shell 命令执行
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14458508/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
node.js shell command execution
提问by Mike Pennington
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...
我仍在努力掌握如何运行 linux 或 windows shell 命令并在 node.js 中捕获输出的更精细的要点;最终,我想做这样的事情......
//pseudocode
output = run_command(cmd, args)
The important piece is that outputmust be available to a globally scoped variable (or object). I tried the following function, but for some reason, I get undefinedprinted to the console...
重要的是它output必须可用于全局范围的变量(或对象)。我尝试了以下功能,但由于某种原因,我被undefined打印到控制台...
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.exechas a 200KB buffer limit.
有人可以帮助我理解为什么try_this()有效,而run_cmd()无效吗?FWIW,我需要使用child_process.spawn,因为child_process.exec有 200KB 缓冲区限制。
Final Resolution
最终决议
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);
采纳答案by James White
There are three issues here that need to be fixed:
这里有三个问题需要解决:
Firstis that you are expecting synchronous behavior while using stdout asynchronously. All of the calls in your run_cmdfunction are asynchronous, so it will spawn the child process and return immediately regardless of whether some, all, or none of the data has been read off of stdout. As such, when you run
首先是您在异步使用 stdout 时期望同步行为。run_cmd函数中的所有调用都是异步的,因此它会生成子进程并立即返回,无论是否从 stdout 中读取了部分、全部或全部数据。因此,当您运行
console.log(foo.stdout);
you get whatever happens to be stored in foo.stdout at the moment, and there's no guarantee what that will be because your child process might still be running.
您现在会得到存储在 foo.stdout 中的任何内容,但不能保证会是什么,因为您的子进程可能仍在运行。
Secondis that stdout is a readable stream, so 1) the data event can be called multiple times, and 2) the callback is given a buffer, not a string. Easy to remedy; just change
其次是 stdout 是一个可读流,所以 1) 数据事件可以被多次调用,2) 回调被赋予一个缓冲区,而不是一个字符串。易于补救;只是改变
foo = new run_cmd(
'netstat.exe', ['-an'], function (me, data){me.stdout=data;}
);
into
进入
foo = new run_cmd(
'netstat.exe', ['-an'], function (me, buffer){me.stdout+=buffer.toString();}
);
so that we convert our buffer into a string and append that string to our stdout variable.
以便我们将缓冲区转换为字符串并将该字符串附加到我们的 stdout 变量中。
Thirdis that you can only know you've received all output when you get the 'end' event, which means we need another listener and callback:
第三,只有在收到 'end' 事件时,您才能知道已收到所有输出,这意味着我们需要另一个侦听器和回调:
function run_cmd(cmd, args, cb, end) {
// ...
child.stdout.on('end', end);
}
So, your final result is this:
所以,你的最终结果是这样的:
function run_cmd(cmd, args, cb, end) {
var spawn = require('child_process').spawn,
child = spawn(cmd, args),
me = this;
child.stdout.on('data', function (buffer) { cb(me, buffer) });
child.stdout.on('end', end);
}
// Run C:\Windows\System32\netstat.exe -an
var foo = new run_cmd(
'netstat.exe', ['-an'],
function (me, buffer) { me.stdout += buffer.toString() },
function () { console.log(foo.stdout) }
);
回答by cibercitizen1
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) });
回答by Mimouni
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. :)
它完美地工作。:)
回答by Tony O'Hagan
Simplest way is to just use the ShellJS lib ...
最简单的方法是只使用 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.orgsupports many common shell commands mapped as NodeJS functions including:
ShellJs.org支持许多映射为 NodeJS 函数的常见 shell 命令,包括:
- cat
- cd
- chmod
- cp
- dirs
- echo
- exec
- exit
- find
- grep
- ln
- ls
- mkdir
- mv
- popd
- pushd
- pwd
- rm
- sed
- test
- which
- 猫
- 光盘
- 修改
- cp
- 目录
- 回声
- 执行
- 出口
- 找
- 格雷普
- 输入
- ls
- 目录
- MV
- 弹出
- 推
- 密码
- R M
- sed
- 测试
- 哪一个
回答by Stephen Quan
@TonyO'Hagan is comprehrensive shelljsanswer, but, I would like to highlight the synchronous version of his answer:
@TonyO'Hagan 是全面的shelljs答案,但是,我想强调他的答案的同步版本:
var shell = require('shelljs');
var output = shell.exec('netstat -rn', {silent:true}).output;
console.log(output);
回答by Logan
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 !
我有一个类似的问题,我最终为此编写了一个节点扩展。您可以查看 git 存储库。它是开源的,免费的,还有所有的好东西!
https://github.com/aponxi/npm-execxi
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 !
ExecXI是一个用C++编写的节点扩展,用于逐条执行shell命令,将命令的输出实时输出到控制台。存在可选的链式和非链式方式;这意味着您可以选择在命令失败后停止脚本(链接),或者您可以继续,好像什么也没发生!
Usage instructions are in the ReadMe file. Feel free to make pull requests or submit issues!
使用说明在自述文件中。随意提出请求请求或提交问题!
I thought it was worth to mention it.
我认为值得一提。
回答by Victorio Berra
Synchronous one-liner:
同步单线:
require('child_process').execSync("echo 'hi'", function puts(error, stdout, stderr) { console.log(stdout) });
require('child_process').execSync("echo 'hi'", function puts(error, stdout, stderr) { console.log(stdout) });
回答by Frank
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))
回答by Chris Eineke
You're not actually returning anything from your run_cmd function.
您实际上并未从 run_cmd 函数返回任何内容。
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. :)
工作得很好。:)
回答by freakish
There's a variable conflict in your run_cmdfunction:
您的run_cmd函数中存在变量冲突:
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 );
});
EDITYou're code fails because you are trying to run dirwhich is notprovided as a separate standalone program. It is a command in cmdprocess. If you want to play with filesystem use native require( 'fs' ).
编辑你的代码,因为你正在尝试运行失败,dir这是不是作为一个单独的独立程序提供。这是一个正在cmd处理的命令。如果您想使用文件系统,请使用 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.
或者(我不推荐)您可以创建一个批处理文件,然后您可以运行该文件。请注意,操作系统默认通过cmd.

