node.js - 如何按顺序执行 shell 命令?

标签 node.js shell

我有一个 shell 命令列表,我想用 nodejs 执行:

// index.js
var commands = ["npm install", "echo 'hello'"];

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

for (var i = 0; i < commands.length; i++) {
    exec(commands[i], function(err, stdout) {
        console.log(stdout);
    });
}

当我运行它时,命令以相反的顺序执行。为什么会这样?如何按顺序执行命令?

更好的是,有没有一种方法可以不使用 nodejs 来执行 shell 命令?我发现它对 shell 的异步处理有点麻烦。

注意:

我知道像 shelljs 这样的库是存在的。我正在尝试仅使用基本 nodejs 来执行此操作。

最佳答案

您的 for 循环正在同时并行执行所有异步操作,因为 exec() 是非阻塞的。他们将完成的顺序取决于他们的执行时间,并且不会是确定的。如果你真的希望它们被排序,那么你必须执行一个,等待它调用它的完成回调然后执行下一个。

您不能使用传统的 for 循环来“等待”异步操作在 Javascript 中完成以便顺序执行它们。相反,您必须手动进行迭代,在上一个迭代的完成回调中启动下一个迭代。我通常的做法是使用一个计数器和一个名为 next() 的本地函数,如下所示:

手动异步迭代

var commands = ["npm install", "echo 'hello'"];

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

function runCommands(array, callback) {

    var index = 0;
    var results = [];

    function next() {
       if (index < array.length) {
           exec(array[index++], function(err, stdout) {
               if (err) return callback(err);
               // do the next iteration
               results.push(stdout);
               next();
           });
       } else {
           // all done here
           callback(null, results);
       }
    }
    // start the first iteration
    next();
}

runCommands(commands, function(err, results) {
    // error or results here
});

ES6 promise

由于 promises 已经在 ES6 中标准化并且现在内置到 node.js 中,所以我喜欢将 Promises 用于我的异步操作:

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

function execPromise = function(cmd) {
    return new Promise(function(resolve, reject) {
        exec(cmd, function(err, stdout) {
            if (err) return reject(err);
            resolve(stdout);
        });
    });
}

var commands = ["npm install", "echo 'hello'"];

commands.reduce(function(p, cmd) {
    return p.then(function(results) {
        return execPromise(cmd).then(function(stdout) {
            results.push(stdout);
            return results;
        });
    });
}, Promise.resolve([])).then(function(results) {
    // all done here, all results in the results array
}, function(err) {
    // error here
});

bluebird promise

使用 Bluebird promise 库,这会更简单:

var Promise = require('bluebird');
var execP = Promise.promisify(require('child_process').exec);

var commands = ["npm install", "echo 'hello'"];
Promise.mapSeries(commands, execP).then(function(results) {
    // all results here
}, function(err) {
    // error here
});

关于node.js - 如何按顺序执行 shell 命令?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36959253/

相关文章:

javascript - 为什么 Buffer slice 不等于它应该是什么?

linux - 如何在 shell 文件中使用 awk 的 $0 变量

linux - for循环在shell脚本中不起作用

ios - 如何从ios swift上传图像到node/mongodb后端

node.js - socket.io 解析请求的 url

windows - 窗口 shell 脚本返回码

linux - 用于监视磁盘 IO 的 shell 脚本无法正常工作

Linux:将命令的输出重定向到 "find"

javascript - 如何使用javascript将字符串编码到Windows 1256中

Node .js : Error: error:0B080074:x509 certificate routines:X509_check_private_key:key values mismatch