[英]node.js execute system command synchronously
我需要在node.js函数中
result = execSync('node -v');
这将同步执行给定的命令行并返回该命令文本的所有标准输出。
附: 同步错误。 我知道。 仅供个人使用。
更新
现在我们有了 mgutz 的解决方案,它为我们提供了退出代码,但没有标准输出! 仍在等待更准确的答案。
更新
mgutz更新了他的答案,解决方案在这里:)
另外,正如dgo.a提到的,有独立模块exec-sync
更新 2014-07-30
ShellJS库到了。 考虑到这是目前最好的选择。
更新 2015-02-10
最后! execSync
0.12 原生支持execSync
。
查看官方文档
请参阅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'));
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...');
});
这是我找到的最简单的方法:
执行同步: https : //github.com/jeremyfa/node-exec-sync
(不要与 execSync 混淆。)
同步执行shell命令。 将此用于迁移脚本、cli 程序,但不适用于常规服务器代码。示例:
var execSync = require('exec-sync');
var user = execSync('echo $USER');
console.log(user);
这在 Node.js 中是不可能的, child_process.spawn
和child_process.exec
都是child_process.exec
开始构建为异步的。
详情见: https : //github.com/ry/node/blob/master/lib/child_process.js
如果你真的想要这个阻塞,那么把之后需要发生的所有事情都放在回调中,或者构建你自己的队列以阻塞方式处理这个,我想你可以使用Async.js来完成这个任务。
或者,如果您有太多时间可以花,可以自己在 Node.js 中进行破解。
只是要补充一点,即使您应该使用它们的用例很少, spawnSync
/ execFileSync
/ execSync
已在这些提交中添加到 node.js: https : //github.com/joyent/node/compare/d58c206862dc...e8df2676748e
原生 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'});
...并且同步执行超时也很好:
const result = execSync('git rev-parse HEAD', {encoding: 'utf8', timeout: 10000});
您可以使用纤维来实现这一点。 例如,使用我的公共节点库,代码如下所示:
result = require('subprocess').command('node -v');
我有一个类似的问题,我最终为此编写了一个节点扩展。 您可以查看 git 存储库。 它是开源的,免费的,还有所有的好东西!
https://github.com/aponxi/npm-execxi
ExecXI是一个用C++编写的节点扩展,用于逐条执行shell命令,将命令的输出实时输出到控制台。 存在可选的链式和非链式方式; 这意味着您可以选择在命令失败(链接)后停止脚本,或者您可以继续,好像什么也没发生!
使用说明在自述文件中。 随意提出请求请求或提交问题!
编辑:
但是它还没有返回标准输出......只是实时输出它们。
现在确实如此。 嗯,我今天刚发布。 也许我们可以以此为基础。
无论如何,我认为值得一提。
我习惯于在回调函数的末尾实现"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);
}
});
};
我实际上遇到过这样的情况,我需要从 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']
编辑:正如所指出的,这实际上并不返回输出或允许您在 Node 程序中使用命令的结果。 另一个想法是使用 LiveScript 回拨。 http://livescript.net/
您可以像这样在 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 需求进行调整
我 5 年来的方式是拥有 2 条线;
const { execSync } = require('child_process');
const shell = (cmd) => execSync(cmd, {encoding: 'utf8'});
然后享受: shell('git remote -v')
或out = shell('ls -l')
.. 等等
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.