在我编写的其他程序中,我使用promises享受了node.js的异步方面。

我想采用相同的编程风格(使用node.js)进行Linux脚本编写。换句话说,我希望能够同时执行多个Linux命令,然后在完成这些命令之后,我希望node.js脚本然后异步执行另一组命令,依此类推(以此类推)。

我遇到了an aritlce,它显示了如何使用node.js执行同步Linux命令,但是我还没有找到类似的教程,该教程涵盖了如何使用node.js管理多个异步Linux命令。

目前可以吗?如果是这样,您能否将我引向一些特定的资源,可以帮助我开始实现这一目标?

最佳答案

我不确定我是否正确,但是我认为您正在寻找execspawn。请参阅related API documentation。文档中有两个命令的示例。
execspawnexecspawn的“简单”版本。前者使用单个回调在命令完成时(仅在命令完全完成/失败时)向用户报告。

child = exec('cat *.js bad_file | wc -l',
  function (error, stdout, stderr) {
    console.log('stdout: ' + stdout);
    console.log('stderr: ' + stderr);
    if (error !== null) {
      console.log('exec error: ' + error);
    }
});

因此,基本上,只有在完全写入stdout/stderr的所有内容都可用时,才调用提供的回调。在进程终止(成功或失败)之后,仅调用回调,并且用户(您)可以对其执行操作。如果失败,error是真实的。
spawn不同,因为您可以侦听stdout/stderr事件。首先,您“产生”一个过程。 spawn函数返回对子进程的引用。
var spawn = require('child_process').spawn;
var ls = spawn('ls', ['-lh', '/usr']);
ls是您产生的子进程。它有两个属性(现在很重要),stdoutstderr是事件发射器。他们正在发出data事件。当将东西写在任一流上时,将调用在data事件上注册的回调。
ls.stdout.on('data', function (data) {
  console.log('stdout: ' + data);
});

ls.stderr.on('data', function (data) {
  console.log('stderr: ' + data);
});

当然还有其他重要事件(请查看文档以获取最新和相关的信息)。
ls.on('close', function (code) {
  console.log('child process exited with code ' + code);
});

当您想要在stdout上捕获内容时,例如在进程运行时,可以使用spawn。一个很好的例子是,如果您要生成一个需要几分钟才能完成的ffmpeg编码任务。您可以侦听stderr(因为ffmpeg将进度信息写入stderr而不是stdout)来解析“进度”信息。

carrier逐行进行

还有一个不错的附加库,可以与spawn一起使用。 It's called carrier。它有助于从生成的进程的stdout/stderr中读取“行”。这很有用,因为传递给回调的data参数不一定包含用\n分隔的“完整”行。 carrier可以帮助您。 (但是,它不会帮助您捕获ffmpeg在stderr上的进度,因为在这种情况下ffmpeg没有写换行符,它只是回车符,该行基本上总是被重写。)

你会这样使用
var carry = require("carrier").carry;
var child = spawn("command");
carry(child.stdout, function(line) {
   console.log("stdout", line);
});

promise 与延期

如果您想使用一个Promise/Deerred风格的方法,那么您可以做一些类似AngularJS所使用的using Q 的事情-或至少做一些非常相似的事情(请参阅该链接以获取有关Promise的完整教程)。
spawn返回一个不是promise的Emitter对象。因此,您必须包装对生成的调用(see Using Deferreds)。
var q = require("q");
var spawn = require("child_process").spawn;

var ls = function() {
  var deferred = q.defer();
  var ls = spawn("ls", ["-lh", "/usr"]);
  ls.stdout.on("data", function(data) {
    deferred.notify({stdout: true, data: data});
  });
  ls.stderr.on("data", function(data) {
    deferred.notify({stderr: true, data: data});
  });
  ls.on("close", function(code) {
    if (code === 0) {
      deferred.resolve();
    } else {
      deferred.reject(code);
    }
  });
  return deferred.promise;
};

通过执行ls()现在会返回一个 promise ,您可以像其他 promise 一样使用它。当它完全解决时,将调用第一个回调。如果发生错误(该过程存在一个非零退出代码),则将调用错误处理程序。在命令执行过程中,将调用第三个回调(通知回调)。
ls().then(function() {
  console.log("child process exited successfully");
}, function(err) {
  console.log("child process exited with code " + err);
}, function(args) {
  if (args.stdout) {
    console.log("stdout: " + args.data);
  } else {
    console.log("stderr: " + args.data);
  }
});

但是,当将某些内容写入stderr时,您可以立即调用拒绝,这是设计决定。回到ffmpeg示例,这对您没有任何好处,因为ffmpeg会将常规信息发送到stderr。但是,它可以与其他命令一起使用。

我想你会明白的:)

例子取自nodejs的文档,因为它们易于理解。

关于javascript - 用于异步Linux脚本的Node.js,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/31683242/

10-15 02:07