Node.js中child_process.fork子进程大量输出后无法自动退出的解决方法
问题根源
当设置silent: true时,子进程的stdout通过管道与主进程通信。你的代码里用worker.stdout.pipe(cache)但没给cache这个Transform流连接下游,触发了Node.js的背压机制:管道缓冲区被填满后,子进程的console.log会阻塞,没法继续执行退出逻辑;主进程又在等子进程触发exit事件才处理输出,两边卡死形成死锁。
解决方案
方案1:用内存缓冲区实时收集输出
放弃Transform流,直接通过data事件把输出存到内存数组,子进程退出后一次性输出:
const child_process = require('child_process'); if (!('IS_WORKER' in process.env)) { const worker = child_process.fork(process.argv[1], process.argv.slice(2), { silent: true, env: { IS_WORKER: 1, }, }); const cache = []; // 实时读取子进程输出并存入缓存 worker.stdout.on('data', (chunk) => { cache.push(chunk); }); console.log('master start'); worker.on('message', e => { console.log(e); }); worker.on('exit', (code, signal) => { console.log(code, signal); // 合并缓存内容并输出 process.stdout.write(Buffer.concat(cache)); }); } else { process.send('hello from child'); console.log(new Array(100000).fill(1).join('')); // 标记输出流结束,帮助主进程识别输出完成 process.stdout.end(); }
方案2:让Transform流保持流动(保留Transform的写法)
如果一定要用Transform流,必须监听它的data事件让数据流持续流动,同时在Transform内部缓存数据:
const child_process = require('child_process'); const stream = require('stream'); class CacheTransform extends stream.Transform { constructor() { super(); this.cache = []; } _transform(chunk, encode, next) { this.cache.push(chunk); next(); // 不向下游传递数据,只缓存 } } if (!('IS_WORKER' in process.env)) { const worker = child_process.fork(process.argv[1], process.argv.slice(2), { silent: true, env: { IS_WORKER: 1, }, }); const cache = new CacheTransform(); worker.stdout.pipe(cache); // 监听data事件,确保流保持流动避免背压 cache.on('data', () => {}); console.log('master start'); worker.on('message', e => { console.log(e); }); worker.on('exit', (code, signal) => { console.log(code, signal); process.stdout.write(Buffer.concat(cache.cache)); }); } else { process.send('hello from child'); console.log(new Array(100000).fill(1).join('')); process.stdout.end(); }
额外提示
- 子进程里的
process.removeAllListeners()和process.channel.unref()可以删掉,这些不是阻塞的原因,反而可能干扰正常的资源清理。 - 添加
process.stdout.end()能明确告诉主进程子进程的输出已经完成,避免不必要的等待。
内容的提问来源于stack exchange,提问作者Ben Lau
相关产品推荐
相关产品推荐

