在我编写的其他程序中,我使用promises享受了node.js的异步方面。
我想采用相同的编程风格(使用node.js)进行Linux脚本编写。换句话说,我希望能够同时执行多个Linux命令,然后在完成这些命令之后,我希望node.js脚本然后异步执行另一组命令,依此类推(以此类推)。
我遇到了an aritlce,它显示了如何使用node.js执行同步Linux命令,但是我还没有找到类似的教程,该教程涵盖了如何使用node.js管理多个异步Linux命令。
目前可以吗?如果是这样,您能否将我引向一些特定的资源,可以帮助我开始实现这一目标?
最佳答案
我不确定我是否正确,但是我认为您正在寻找exec
和spawn
。请参阅related API documentation。文档中有两个命令的示例。exec
和spawn
exec
是spawn
的“简单”版本。前者使用单个回调在命令完成时(仅在命令完全完成/失败时)向用户报告。
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
是您产生的子进程。它有两个属性(现在很重要),stdout
和stderr
是事件发射器。他们正在发出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/