如何从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刷新子进程的主要内容,如果未能解决你的问题,请参考以下文章

关于wait 和 exit

golang 热重启

Linux学习-进程管理

Shell脚本入门 07:进程与信号

Shell脚本入门 07:进程与信号

38父进程子进程进程组作业和会话