如何从nodejs刷新子进程
Posted
技术标签:
【中文标题】如何从nodejs刷新子进程【英文标题】:How can I flush a child process from nodejs 【发布时间】:2016-10-17 13:19:46 【问题描述】:我使用 spawn 从 nodejs 调用一个可执行的 C 程序,但 C 程序似乎不是每次都被刷新。那么,我的节点程序只能在缓冲区满(4K)或子进程退出时输出子进程的stdout。
为了简单的场景,两部分代码应该是:
invoke.js
var spawn = require("child_process").spawn;
var ps = spawn("./echo");
ps.stdout.on("data", (data) =>
console.log(`$data`);
);
process.on("SIGINT", ps.kill);
echo.c
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
static volatile int keep = 1;
void intHandler(int d)
keep = 0;
int main()
signal(SIGINT, intHandler);
int count = 0;
while(keep)
printf("%d hello world!\r\n", ++count);
sleep(1);
如何在 invoke.js 同步中获取 echo 的输出?一件重要的事情是我无法修改 echo.c,我只有二进制文件
【问题讨论】:
【参考方案1】:您需要阅读有关子进程/分叉以及如何将子输出通过管道传输到父进程的文档: https://nodejs.org/api/child_process.html#child_process_options_stdio
'pipe' - 相当于 ['pipe', 'pipe', 'pipe'](默认) 'ignore' - 相当于 ['ignore', 'ignore', 'ignore'] 'inherit' - 相当于 [process.stdin, process.stdout, process.stderr] 或 [0,1,2]
在你的情况下,如果你不需要对输出做更复杂的事情,你可以去掉 on.data
事件监听器,只用继承选项初始化生成的进程。我已经修改了 SIGINT 事件绑定,以更清楚地表明调用了 ps.kill。
var spawn = require('child_process').spawn;
var ps = spawn('./echo', stdio: 'inherit' );
process.on('SIGINT', function ()
console.log('sigint received');
ps.kill();
);
【讨论】:
那太好了,还有一个问题是如果我还在使用on.data,有什么办法可以解决这个问题吗? @yuizhou 我刚刚发现您的代码也可以正常工作。只是缓冲了一个特定的大小,在某个点之后,您将在控制台中看到正在打印的结果。如果您修改 echo.c 文件并在其中放入更多带有更大字符串的 printfs,您会看到这种情况。 我在 linux 环境下运行它。当 echo 程序的输出为 stdout 时,到达 \n 时会自动刷新,但一旦 io 重定向到其他目的地,其输出将放入 4K 大小的缓冲区。我只能在缓冲区已满或重定向情况下进程退出时看到输出。所以我想知道我可以在我的 nodejs 程序中修改缓冲区的大小或强制刷新流,因为我无法在重定向的情况下修改 echo 程序。【参考方案2】:我发现 execa 对此很有用。
【讨论】:
我认为这个库是用于同步过程的,但是我调用的 C 程序包含一个 while-true 循环来打印一些东西,直到用户终止它才能停止。所以这个库似乎不适合我的情况。无论如何,非常感谢。【参考方案3】:https://nodejs.org/dist/latest-v12.x/docs/api/process.html#process_a_note_on_process_i_o
Windows 和 POSIX 之间存在差异。
如果 child_process 在 Windows 上生成,则只有 TTY 类型的 stdout 异步工作。
inherit
选项使 child_process 异步,因为 process.stdout
是 TTY 类型。
【讨论】:
以上是关于如何从nodejs刷新子进程的主要内容,如果未能解决你的问题,请参考以下文章