捕获child_process spawnSync或execSync stdout

时间:2015-08-11 15:31:13

标签: javascript node.js

是否有一种简单的方式来捕获child_process spawnSyncexecSync stdout / stderr?我已经看到其他帖子几年前说过,因为它是同步的,所以当时不可能。

我有一个问题,我需要捕获另一个线程输出,所以我可以解析发送到stdout的内容。问题是,我没有找到任何过去只使用spawn并使用stdout.on事件。

这会导致问题,因为我的程序并不是异步的。

修改

我拥有的工具名为eslint-watch。它增加了像文件监视这样的eslint功能,并指定了一个默认目录。问题在于这个讨论https://github.com/eslint/eslint/issues/2831我们得出结论,我需要将eslint作为二进制文件执行并从中获取帮助选项。

在eslint返回其帮助选项后,我会解析它们并将它们汇集到发言人中。所以我的包装器与eslint具有相同的帮助上下文菜单,但也有我的命令。问题是抓住帮助是我做的第一件事之一,所以我可以从终端解析命令。

3 个答案:

答案 0 :(得分:2)

我不确定我是否理解正确,并且猜测anwser不再对海报感兴趣了。然而,由于我在这里做了类似的事情,所以:

var karma = spawnSync("node",
    ["node_modules/karma/bin/karma", "start", "karma.conf.js", "--single-run"],
    {
        stdio: [null, process.stdout, process.stderr]
    }
);
if (karma.status != 0) {
    console.log(`Karma reported error(s) (${karma.status}). Build aborted\n`.red);
    process.exit(1);
} else {
    console.log(`Karma success\n`.green);
}

以上示例启动Karma并执行配置文件中指定的测试。我想要的是在webpack设置为发布版本时强制执行测试。我们的想法是,即使构建配置错误,构建服务器也无法在未经过测试的情况下执行发布。

这个将上面的块引入webpack.conf.js并阻塞执行线程直到karma完成,同时将karmas stdout / err传送到控制台上。使用spawnSync而不是spawn只是必要的,因为一旦线程从webpack.conf.json返回,Webpack立即启动并可能使用失败的测试构建项目。

原始问题中描述的内容听起来像是异步的东西。调用该进程,一旦stdout到达,就在事件处理程序中添加您的附加输出。 如果您仍然不能同步执行,则stdio数组只需要流。这意味着您可以为stdout创建一个包装器流,并告诉子进程使用它。

答案 1 :(得分:1)

参考require('child_process').spawnSync() or .exexSync(),Node API docs非常清楚地表明:

  

这些方法是同步的,这意味着它们将阻止事件循环,暂停执行代码直到生成的进程退出。

     

阻止这些调用对于简化通用脚本任务和简化启动时应用程序配置的加载/处理非常有用。

所以,你是正确的。在同步运行外部进程时无法处理stdio事件,因为Node事件循环将暂停,直到外部进程完成。

您可以考虑使用shell输出重定向(即使用bash:stdout)将进程stderr和/或COMMAND 1>stdout.txt 2>stderr.log捕获到一个或多个文件,您可以通过运行命令来执行此操作在bash shell中。

从Node执行此操作的最简单方法是:

文件:runner.sh

#/bin/sh
PATH_TO_YOUR_COMMAND_HERE 1>command_stdout.txt 2>command_stderr.txt

文件:nodeprocess.js

var fs = require('fs'),
    spawnSync = require('child_process').spawnSync,
    args = ['/bin/sh', 'runner.sh'];

spawnSync(args); // Event Loop will wait here.

if(fs.existsSync('./command_stdout.txt')){
  // process standard output from your command here
}
if(fs.existsSync('./command_stderr.txt')){
  // process error output from your command here
}

当然,您应该执行所有正确的文件系统卫生操作,例如将输出文件写入/tmp并在完成后将其删除,但我会将这些内容留给您想象。

我很好奇为什么你不能使用.spawn().fork(),因为如果命令可以从命令行运行,那么就没有理由不能从Node异步运行它。

答案 2 :(得分:0)

自您进行编辑以来,一切都已改变。

execSync现在在完成时返回stdout。

//will return date() on *nix systems;
console.log(require("child_process").execSync(`date`).toString());

>>> Fri Jul 10 14:19:41 UTC 2020