如何按顺序执行shell命令? [英] How can I execute shell commands in sequence?

查看:133
本文介绍了如何按顺序执行shell命令?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个要使用 nodejs 执行的 shell 命令列表:

I have a list of shell commands I want to execute with 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);
    });
}

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

When I run this, the commands are executed in the reverse order. Why is this happening? How do i execute the commands in sequence?

更好的是,有没有办法在不使用 nodejs 的情况下执行 shell 命令?我发现它对 shell 的异步处理有点麻烦.

Better yet, is there a way to execute shell commands without using nodejs? I find its async handling of the shell a little cumbersome.

注意:

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

I know that libraries like shelljs exist. I'm trying to do this with base nodejs only.

推荐答案

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

Your for loop is executing all your asynchronous operation in parallel at once because exec() is non-blocking. The order they will complete depends upon their execution time and will not be determinate. If you truly want them to be sequenced, then you have to execute one, wait for it to call it's completion callback and then execute the next one.

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

You can't use a traditional for loop to "wait" on an asynchronous operation to complete in Javascript in order to execute them sequentially. Instead, you have to make the iteration manually where you kick off the next iteration in the completion callback of the previous one. My usual way of doing that is with a counter and a local function called next() like this:

手动异步迭代

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 已在 ES6 中标准化并且现在已内置到 node.js 中,因此我喜欢将 Promise 用于我的异步操作:

Since promises have been standardized in ES6 and are built into node.js now, I like to use Promises for my async operations:

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 承诺库,这会更简单:

Using the Bluebird promise library, this would be even simpler:

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

这篇关于如何按顺序执行shell命令?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆