[英]Node.js for Asynchronous Linux Scripting
我不确定我是不对,但我认为你正在寻找exec
和spawn
。 请参阅相关的API文档 。 文档中有两个命令的示例。
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);
}
});
所以基本上提供的回调函数只调用,当被写入标准输出/标准错误都可用, 完全 。 在进程终止(成功或失败)之后,才会调用回调,用户(您)可以对其进行操作。 如果它失败了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
一起使用。 它被称为载体 。 它有助于从生成的进程的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 / deferred样式方法,那么您可以使用AngularJS 使用的Q
来执行类似下面的操作 - 或者至少非常相似(请参阅有关promises的完整教程的链接)。
spawn
返回一个不是promise的Emitter
对象。 因此,您必须将调用包装为spawn( 请参阅使用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的文档,因为它们很好理解。
在核心节点库中,同步函数将Sync
附加到函数名称。 他们正在使用child_process.execFileSync ,因此您应该为该函数的异步版本寻找child_process.execFile 。
我推荐一种结合发电机和承诺的方法。 以下是先决条件:
--harmony
标志的节点0.11或更高版本,或任何版本的io.js(不需要标志)。 然后做你想要的那种事情:
var co = require('co');
var adapt = require('ugly-adapter');
var childProcessExec = require('child_process').exec;
var exec = adapt.part(childProcessExec);
co(function*() {
// run commands in parallel by yielding
// a single object or array
var result = yield {
listing: exec('ls -l'),
mkdirResult: exec('mkdir foo'),
blah: exec('echo "blah blah"'),
};
console.log(result.blah); // "blah blah"
// run commands in series by yielding
// one thing at a time
var listing = yield exec('ls -l');
var mkdirResult = yield exec('mkdir foo2');
var blah = yield exec('echo "blah blah"');
console.log(blah); // "blah blah"
}).catch(function(err){
// this handles any possible errors
// thrown by the above
console.error(err.stack);
process.exit(1);
});
yield
关键字使函数暂停,同时co
展开promise并将结果发送回函数。 注意:库co
实际上只是async / await的一个临时替代,它在es7中出现并且工作方式基本相同。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.