Node.js多进程:如何实时获取子进程输出而非进程结束后统一输出
如何让Node.js子进程实时输出内容?
你当前使用的child_process.exec会缓存子进程的所有输出,直到进程完全结束后才一次性返回结果,这就是为什么要等所有子进程结束才能看到输出。要实现实时打印,需要改用child_process.spawn——它以流的方式处理子进程的stdout和stderr,可以在输出产生时立即捕获。
修改后的代码如下:
const { spawn } = require("child_process"); const NUM_WORKERS = 5; for (let i = 0; i < NUM_WORKERS; ++i) { // 使用spawn创建子进程,拆分命令与参数 const worker = spawn("node", ["-e", "console.log(process.env.MY_VAR);"], { env: { MY_VAR: String(i), // spawn要求环境变量值为字符串类型 PATH: process.env.PATH // 继承父进程PATH,避免子进程找不到node命令 } }); // 实时监听stdout输出 worker.stdout.on("data", (data) => { const output = data.toString().trim(); if (output) { console.log(`[stdout#${i}] ${output}`); } }); // 实时监听stderr输出 worker.stderr.on("data", (data) => { const output = data.toString().trim(); if (output) { console.log(`[stderr#${i}] ${output}`); } }); // 监听子进程退出事件 worker.on("close", (code) => { if (code !== 0) { console.log(`[worker#${i}] 退出,退出码: ${code}`); } }); // 监听子进程启动失败事件 worker.on("error", (err) => { console.log(`[worker#${i}] 启动失败:`, err); }); }
关键改动说明:
- 替换为spawn:spawn是Node.js处理流式输出的标准API,不会缓存子进程输出,每有数据产生就触发
data事件,实现实时打印。 - 命令参数拆分:spawn要求将命令和参数分开传入(第一个参数为命令,第二个为参数数组),不能像exec那样传入整串命令。
- 环境变量处理:spawn的env对象中值必须是字符串,因此将数字
i转为String;同时继承父进程的PATH,避免子进程找不到系统命令。 - 流式事件监听:分别给stdout和stderr绑定
data事件,每次获取到数据就立即处理打印,注意将Buffer转为字符串并去除多余换行。
exec与spawn的适用场景:
exec:适合子进程输出内容少、需要一次性获取完整结果的场景(比如执行简单shell命令获取返回值)。spawn:适合需要实时处理输出、输出内容大或持续产生输出的场景(比如启动服务、执行长时间运行的脚本)。
内容的提问来源于stack exchange,提问作者Bob
相关产品推荐
相关产品推荐

