Node.js同步执行系统命令

我需要node . js函数

result = execSync('node -v');

同步将执行给定的命令行,并返回该命令文本的所有stdout。

ps.同步错误。我知道。仅供个人使用。

更新

现在我们有了mgutz的解决方案,它给出了退出代码,但没有stdout!还在等更确切的答案。

更新

mgutz更新了他的答案,解决方案在这里:)
另外,正如dgo.a所提到的,存在独立模块exec-sync

更新2014-07-30

ShellJS lib到达。考虑到这是目前最好的选择。


更新2015-02-10

. 终于! NodeJS 0.12原生支持execSync 参见官方文档

185299 次浏览

这在Node.js中是不可能的,child_process.spawnchild_process.exec都是从头构建为异步的。

详细信息请参见:https://github.com/ry/node/blob/master/lib/child_process.js

如果你真的想要这种阻塞,那么把所有需要发生的事情都放在回调中,或者构建自己的队列以阻塞的方式处理它,我认为你可以使用Async.js来完成这个任务。

或者,如果你有太多的时间,可以在Node.js中自己动手。

参见execSync库。

node-ffi很容易做到。我不推荐服务器进程,但对于一般的开发实用程序,它可以完成任务。安装库。

npm install node-ffi

示例脚本:

var FFI = require("node-ffi");
var libc = new FFI.Library(null, {
"system": ["int32", ["string"]]
});


var run = libc.system;
run("echo $USER");

[编辑2012年6月:如何获得STDOUT]

var lib = ffi.Library(null, {
// FILE* popen(char* cmd, char* mode);
popen: ['pointer', ['string', 'string']],


// void pclose(FILE* fp);
pclose: ['void', [ 'pointer']],


// char* fgets(char* buff, int buff, in)
fgets: ['string', ['string', 'int','pointer']]
});


function execSync(cmd) {
var
buffer = new Buffer(1024),
result = "",
fp = lib.popen(cmd, 'r');


if (!fp) throw new Error('execSync error: '+cmd);


while(lib.fgets(buffer, 1024, fp)) {
result += buffer.readCString();
};
lib.pclose(fp);


return result;
}


console.log(execSync('echo $HOME'));
我习惯于在回调函数的末尾实现"synchronous"的东西。不是很好,但是很有效。如果你需要实现一系列命令行执行,你需要将exec包装到某个命名函数中并递归调用它。 这个模式似乎对我有用:

SeqOfExec(someParam);


function SeqOfExec(somepParam) {
// some stuff
// .....
// .....


var execStr = "yourExecString";
child_proc.exec(execStr, function (error, stdout, stderr) {
if (error != null) {
if (stdout) {
throw Error("Smth goes wrong" + error);
} else {
// consider that empty stdout causes
// creation of error object
}
}
// some stuff
// .....
// .....


// you also need some flag which will signal that you
// need to end loop
if (someFlag ) {
// your synch stuff after all execs
// here
// .....
} else {
SeqOfExec(someAnotherParam);
}
});
};

你可以在nodejs中执行同步shell操作,如下所示:

var execSync = function(cmd) {


var exec  = require('child_process').exec;
var fs = require('fs');


//for linux use ; instead of &&
//execute your command followed by a simple echo
//to file to indicate process is finished
exec(cmd + " > c:\\stdout.txt && echo done > c:\\sync.txt");


while (true) {
//consider a timeout option to prevent infinite loop
//NOTE: this will max out your cpu too!
try {
var status = fs.readFileSync('c:\\sync.txt', 'utf8');


if (status.trim() == "done") {
var res = fs.readFileSync("c:\\stdout.txt", 'utf8');
fs.unlinkSync("c:\\stdout.txt"); //cleanup temp files
fs.unlinkSync("c:\\sync.txt");
return res;
}
} catch(e) { } //readFileSync will fail until file exists
}


};


//won't return anything, but will take 10 seconds to run
console.log(execSync("sleep 10"));


//assuming there are a lot of files and subdirectories,
//this too may take a while, use your own applicable file path
console.log(execSync("dir /s c:\\usr\\docs\\"));

编辑-本例适用于windows环境,如有必要可根据您自己的linux需求进行调整

在node.js中有一个很棒的流控制模块,叫做asyncblock。如果在函数中包装代码对您的情况是OK的,那么可以考虑以下示例:

var asyncblock = require('asyncblock');
var exec = require('child_process').exec;


asyncblock(function (flow) {
exec('node -v', flow.add());
result = flow.wait();
console.log(result);    // There'll be trailing \n in the output


// Some other jobs
console.log('More results like if it were sync...');
});

您可以使用纤维来实现这一点。例如,使用我的Common Node库,代码看起来像这样:

result = require('subprocess').command('node -v');

这是我发现的最简单的方法:

< p > exec-Sync: https://github.com/jeremyfa/node-exec-sync
(不要与execSync混淆。)
同步执行shell命令。用于迁移脚本,cli程序,但不用于常规的服务器代码

例子:

var execSync = require('exec-sync');
var user = execSync('echo $USER');
console.log(user);

我也遇到过类似的问题,最后我为此写了一个节点扩展。您可以查看git存储库。它是开源的,免费的,还有所有这些好东西!

https://github.com/aponxi/npm-execxi

ExecXI是一个用c++编写的用于执行shell命令的节点扩展 依次将命令的输出输出到控制台中 实时的。有可选的链式和非链式方式;意义 您可以选择在命令失败后停止脚本

.

.

.

.

使用说明在自述文件。请随意进行拉请求或提交问题!

嗯,我今天才发布。也许我们可以以此为基础。

不管怎样,我觉得值得一提。

我实际上遇到过这样的情况,我需要从一个包中一个接一个地运行多个命令。json preinstall脚本的一种方式,将工作在Windows和Linux/OSX,所以我不能依赖于非核心模块。

这就是我想到的:

#cmds.coffee
childproc = require 'child_process'


exports.exec = (cmds) ->
next = ->
if cmds.length > 0
cmd = cmds.shift()
console.log "Running command: #{cmd}"
childproc.exec cmd, (err, stdout, stderr) ->
if err? then console.log err
if stdout? then console.log stdout
if stderr? then console.log stderr
next()
else
console.log "Done executing commands."


console.log "Running the follows commands:"
console.log cmds
next()

你可以这样使用它:

require('./cmds').exec ['grunt coffee', 'nodeunit test/tls-config.js']

EDIT:正如所指出的,这实际上并不返回输出,也不允许您在Node程序中使用命令的结果。另一个想法是使用LiveScript回调。http://livescript.net/

只是补充一点,尽管你应该使用它们的用例很少,但spawnSync / execFileSync / execSync在这些提交中被添加到node.js

使用ShellJS模块。

执行函数没有提供回调。

例子:

var version = exec('node -v').output;

Node.js(从0.12版本开始-暂时如此)支持execSync:

child_process.execSync(command[, options])

你现在可以直接这样做:

const execSync = require('child_process').execSync;
code = execSync('node -v');

它会如你所愿。(默认为将i/o结果管道到父进程)。注意,你现在也可以spawnSync

本地Node.js解决方案是:

const {execSync} = require('child_process');


const result = execSync('node -v'); // 👈 this do the trick

只要注意一些命令返回 Buffer而不是string。如果你需要string,只需将encoding添加到execSync选项:

const result = execSync('git rev-parse HEAD', {encoding: 'utf8'});

... 在sync exec上设置timeout也是很好的:

const result = execSync('git rev-parse HEAD', {encoding: 'utf8', timeout: 10000});

5年来,我的方法是有两条线;

const { execSync } = require('child_process');
const shell = (cmd) => execSync(cmd, {encoding: 'utf8'});
< p >然后享受: shell('git remote -v')out = shell('ls -l') .. 所以在< / p >