Node.js运行外部脚本如何实时获取逐行输出而非进程结束后获取
Node.js 子进程实时获取输出解决方案
问题原因
你目前使用的child_process.exec()方法默认会将子进程的所有stdout、stderr输出缓存到内存中,只有等子进程完全退出后才会触发回调返回全部缓存内容,因此无法实现实时获取逐行输出的需求。同时你原有代码中stdout.message、stderr.message的写法是错误的,exec回调返回的stdout、stderr本身就是Buffer/字符串类型,不存在message属性。
解决方案
改用child_process.spawn()方法,该方法会返回子进程实例,可通过监听stdout、stderr的data事件,在每次有新输出产生时即时触发回调,满足实时获取输出的要求。
修正后代码示例
const { spawn } = require('child_process'); // 替换原有的exec调用 const childProcess = spawn(line, { shell: true, // 开启后支持直接传入完整命令字符串,和原exec用法保持一致 encoding: 'utf-8' }); // 监听实时标准输出 childProcess.stdout.on('data', (data) => { const stdoutStr = data.toString(); // 原有业务逻辑 if (stdoutStr.includes("Se fini")) { console.log("Server end task"); _generating = false; } const _out = "------- STD OUT ------- (" + Today() + ") : \n " + stdoutStr; console.log(_out); WriteLog(_out); }); // 监听实时标准错误输出 childProcess.stderr.on('data', (data) => { const stderrStr = data.toString(); const _out = "!!!!!!! STDERROR EN ComandLine (" + Today() + ") : \n " + stderrStr; console.log(_out); WriteLog(_out); socket.send("ERROR"); }); // 监听进程启动/执行错误(如命令不存在、权限不足等) childProcess.on('error', (error) => { const _out = "!!!!!!! ERROR EN ComandLine (" + Today() + ")-------!! : \n " + error.message; console.log(_out); WriteLog(_out); socket.send("ERROR"); }); // 可选:监听进程退出事件 childProcess.on('close', (code) => { console.log(`子进程执行结束,退出码:${code}`); });
注意事项
- 如果子进程内部自带输出缓冲逻辑(比如C语言程序默认行缓冲,只有输出满一行才会刷新缓冲区),会导致实时性受影响,这种情况需要修改子进程代码关闭缓冲,或使用伪终端模式执行命令
- 如果需要合并stdout和stderr的输出,可以在spawn配置中设置
stderr: 'stdout'将错误输出重定向到标准输出流统一处理
内容的提问来源于stack exchange,提问作者segu
相关产品推荐
相关产品推荐

