NodeJS环境下如何获取spawn子进程终止前的实时stdout输出数据
问题原因
该问题由Perl侧的标准输出默认缓冲策略导致,与Node.js侧逻辑无关:
- stderr默认无缓冲,所以可以实时触发
data事件拿到输出 - stdout在输出目标为管道(Node.js spawn创建子进程时默认用管道连接标准流)时,默认启用全缓冲,仅当缓冲区满或进程退出时才会批量输出内容,因此只能在子进程终止后拿到全部stdout内容。
可行解决方案
最优方案:Perl侧配置自动刷新(无需修改业务代码)
直接在spawn调用Perl的参数中新增-Mautoflush=STDOUT,即可强制Perl进程启动时自动打开stdout的自动刷新开关,每一次输出都会实时推送,修改后的代码如下:spawn() { const asLibs = []; this._aLibs.forEach( (sLib) => { asLibs.push("-I", sLib); } ); const child = cp.spawn( this._path_perl, // 新增-Mautoflush=STDOUT参数即可生效 [ ...asLibs, '-Mautoflush=STDOUT', `-m${this._module}`, '-e', `${this._module}::${this._module_fn}()`, ] ); child.stdout.on('data', (data) => { console.log('stdout: ' + data); }); child.stderr.on('data', (data) => { console.log('stderr: ' + data); }); }如果可以修改Perl业务代码,也可以在你调用的
${this._module_fn}函数的开头添加一行代码$| = 1;,效果和上述参数配置完全一致。备选方案:Node.js侧使用伪终端适配
如果完全无法修改Perl相关的任何配置和代码,可以在Windows环境下引入node-pty依赖,用伪终端模式启动Perl子进程,此时Perl会认为stdout是输出到交互式终端,默认启用行缓冲,即可实时拿到输出内容。
内容的提问来源于stack exchange,提问作者Sadko
相关产品推荐
相关产品推荐

