node.js同步执行系统命令

我需要在node.js函数中

result = execSync('node -v'); 

这将同步执行给定的命令行,并返回所有由该命令文本标准输出。

PS。 同步是错误的。 我知道。 仅供个人使用。

UPDATE

现在我们有mgutz的解决scheme,它给了我们退出代码,但不是标准输出! 还在等待更精确的答案。

UPDATE

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

更新2014-07-30

ShellJS lib到达。 考虑这是现在最好的select。


更新2015-02-10

最后! execSync 0.12本地支持execSync
查看官方文档

NodeJS 0.12和IO.js 1.10现在支持execSync

 child_process.execSync(command[, options]) 

你现在可以直接做到这一点:

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

它会做你所期望的。 (默认将io结果传递给父进程)。 请注意,您现在也可以spawnSync

请参阅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月:如何获得标准输出]

 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')); 

使用ShellJS模块。

exec函数不提供callback。

例:

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

node.js中有一个非常好的模块,称为asyncblock 。 如果包装在一个函数的代码是你的情况下,可以考虑下面的例子:

 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...'); }); 

这在Node.js中是不可能的, child_process.spawnchild_process.exec都是从头build立起来的asynchronous。

有关详细信息,请参阅: https : //github.com/ry/node/blob/master/lib/child_process.js

如果你真的想要这个阻塞,那么把所有需要事件发生在callback中,或者build立你自己的队列来阻塞,我想你可以使用Async.js来完成这个任务。

或者,如果你有太多的时间花在Node.js上,那就自己来吧。

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

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); 

只要补充一点,即使应用程序很less使用它们, spawnSync / execFileSync / execSync在这些提交中添加到node.js中: https : //github.com/joyent/node/compare/d58c206862dc…e8df2676748e

您可以使用光纤来实现这一点。 例如,使用我的公共节点库 ,代码如下所示:

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

我习惯于在callback函数结束时实现"synchronous"东西。 不是很好,但它的作品。 如果你需要实现一系列的命令行执行,你需要将exec包装到某个命名的函数中,并recursion调用它。 这种模式对我来说似乎是可用的:

 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); } }); }; 

我有一个类似的问题,我最终为此写了一个节点扩展。 你可以看看git仓库。 它是开源的,免费的,所有的好东西!

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

ExecXI是用C ++编写的一个节点扩展,用于逐个执行shell命令,将命令的输出实时输出到控制台。 目前有可select的链接和解开的方式; 这意味着您可以select在命令失败(链接)后停止脚本,也可以继续操作,就好像什么也没有发生!

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

编辑: 但是,它不返回标准输出尚未…只是实时输出它们。 现在呢。 那我今天才发布呢 也许我们可以build立它。

无论如何,我认为这是值得一提的。

您可以在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 /sc:\\usr\\docs\\")); 

编辑 – 这个例子是为Windows环境而devise的,如果需要的话可以调整你自己的linux需求

实际上,我需要从package.json预安装脚本中一个接一个地运行多个命令,这种方式可以在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'] 

编辑:正如指出的,这实际上不会返回输出或允许您在节点程序中使用命令的结果。 另一个想法是使用LiveScript后退。 http://livescript.net/