javascript - node.js shell命令执行
我仍然试图掌握如何运行linux或windows shell命令以及在node.js中捕获输出的更好点; 最终,我想做这样的事......
//pseudocode
output = run_command(cmd, args)
重要的是child_process.exec必须可用于全局范围的变量(或对象)。 我尝试了以下功能,但出于某种原因,我将run_cmd()打印到控制台...
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"
我无法理解代码在上面的位置......这个模型的一个非常简单的原型工作......
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"
有人可以帮我理解为什么child_process.exec有效,而run_cmd()不行吗? FWIW,我需要使用child_process.exec,因为child_process.exec具有200KB的缓冲区限制。
最终决议
我接受了James White的回答,但这是对我有用的确切代码......
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);
10个解决方案
88 votes
这里有三个问题需要修复:
首先,您在异步使用stdout时期望同步行为。 run_cmd函数中的所有调用都是异步的,因此它将生成子进程并立即返回,无论是否从stdout读取了部分,全部或全部数据。 因此,当你跑步
console.log(foo.stdout);
你得到了当前存储在foo.stdout中的任何内容,并且无法保证会发生什么,因为你的子进程可能仍在运行。
其次是stdout是一个可读的流,因此1)数据事件可以被多次调用,2)回调被赋予缓冲区,而不是字符串。 易于补救; 只是改变
foo = new run_cmd(
'netstat.exe', ['-an'], function (me, data){me.stdout=data;}
);
成
foo = new run_cmd(
'netstat.exe', ['-an'], function (me, buffer){me.stdout+=buffer.toString();}
);
这样我们就可以将缓冲区转换为字符串,并将该字符串附加到我们的stdout变量中。
第三,当你收到'结束'事件时,你只能知道你已收到所有输出,这意味着我们需要另一个监听器和回调:
function run_cmd(cmd, args, cb, end) {
// ...
child.stdout.on('end', end);
}
所以,你的最终结果如下:
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) }
);
James White answered 2019-07-12T15:45:46Z
76 votes
接受的答案(第三点)的简化版本,对我有用。
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) });
} // ()
用法:
run_cmd( "ls", ["-l"], function(text) { console.log (text) });
run_cmd( "hostname", [], function(text) { console.log (text) });
cibercitizen1 answered 2019-07-12T15:46:14Z
45 votes
我更简洁地使用了这个:
var sys = require('sys')
var exec = require('child_process').exec;
function puts(error, stdout, stderr) { sys.puts(stdout) }
exec("ls -la", puts);
它完美地运作。:)
Mimouni answered 2019-07-12T15:46:50Z
42 votes
最简单的方法就是使用ShellJS lib ...
$ npm install [-g] shelljs
EXEC示例:
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支持许多映射为NodeJS函数的常见shell命令,包括:
猫
光盘
CHMOD
CP
迪尔斯
回声
EXEC
出口
找
grep的
LN
LS
MKDIR
MV
POPD
PUSHD
PWD
R M
SED
测试
哪一个
Tony O'Hagan answered 2019-07-12T15:49:44Z
4 votes
我遇到了类似的问题,最后我为此编写了一个节点扩展。 你可以看看git存储库。 它是开源的,免费的,所有这些好东西!
[https://github.com/aponxi/npm-execxi]
ExecXI是用C ++编写的节点扩展,用于执行shell命令 逐个输出命令的输出到控制台 即时的。 存在可选的链式和无链接方式; 含义 您可以选择在命令失败后停止脚本 (链式),或者你可以继续,好像什么也没发生过!
使用说明位于自述文件中。 随意提出拉动请求或提交问题!
我认为值得一提。
Logan answered 2019-07-12T15:50:28Z
3 votes
@TonyO'Hagan是全面的shelljs答案,但是,我想突出他的答案的同步版本:
var shell = require('shelljs');
var output = shell.exec('netstat -rn', {silent:true}).output;
console.log(output);
Stephen Quan answered 2019-07-12T15:50:54Z
1 votes
同步单线程:
require('child_process').execSync("echo 'hi'", function puts(error, stdout, stderr) { console.log(stdout) });
Victorio Berra answered 2019-07-12T15:51:28Z
0 votes
cmd函数中存在可变冲突:
var me = this;
child.stdout.on('data', function(me, data) {
// me is overriden by function argument
cb(me, data);
});
只需将其更改为:
var me = this;
child.stdout.on('data', function(data) {
// One argument only!
cb(me, data);
});
为了看到错误总是添加这个:
child.stderr.on('data', function(data) {
console.log( data );
});
编辑您的代码失败,因为您尝试运行cmd,这不是作为单独的独立程序提供的。 它是cmd进程中的命令。 如果你想使用文件系统使用原生require( 'fs' )。
或者(我不建议)您可以创建一个批处理文件然后运行。 请注意,默认情况下,OS会通过cmd触发批处理文件。
freakish answered 2019-07-12T15:52:27Z
0 votes
你实际上没有从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...'
工作得很好。:)
Chris Eineke answered 2019-07-12T15:53:04Z
0 votes
获奖最多的答案:
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) })
})
}
使用:
runCmd('ls').then(ret => console.log(ret))
Frank answered 2019-07-12T15:53:33Z