如何用Node脚本启动子进程并捕获stdout,退出时终止子进程
解决方案
可以实现需求,你的现有代码问题在于process.on('exit')触发时机太晚,此时进程已进入退出流程,可能无法及时终止子进程。需要监听信号事件并处理未捕获异常,确保父进程退出前先终止子进程。
修改后的代码如下:
const childProcess = require('child_process'); let myVar = ''; // 启动子进程,明确设置stdio为pipe(默认也是pipe,但显式设置更清晰) const child = childProcess.spawn('npm', ['start'], { stdio: ['ignore', 'pipe', 'pipe'] // stdin忽略,stdout和stderr用pipe }); // 捕获子进程stdout,存入myVar(多次输出时用+=拼接,覆盖的话用=) child.stdout.on('data', (data) => { myVar += data.toString(); // 如果每次输出都覆盖之前的内容,就用:myVar = data.toString(); }); // 监听子进程stderr,避免错误信息泄漏到终端(可选,可存入其他变量) child.stderr.on('data', (data) => { // 此处可选择忽略或记录到日志,不输出到终端 }); // 统一的清理退出逻辑 function cleanupAndExit() { if (!child.killed) { child.kill('SIGTERM'); // 超时未退出则强制杀死 setTimeout(() => { if (!child.killed) { child.kill('SIGKILL'); } process.exit(0); }, 1000); } else { process.exit(0); } } // 监听系统终止信号 process.on('SIGINT', cleanupAndExit); process.on('SIGTERM', cleanupAndExit); // 处理未捕获异常 process.on('uncaughtException', (err) => { console.error('未捕获异常:', err); cleanupAndExit(); }); // 处理未处理的Promise拒绝 process.on('unhandledRejection', (reason, promise) => { console.error('未处理的Promise拒绝:', reason); cleanupAndExit(); });
关键说明:
- 信号监听:通过监听
SIGINT(Ctrl+C触发)和SIGTERM(系统终止命令触发)信号,在收到信号时优先终止子进程,再退出父进程,避免子进程成为孤儿进程继续运行。 - 异常处理:捕获
uncaughtException和unhandledRejection,防止父进程因意外异常直接退出,确保子进程能被及时终止。 - stdio配置:显式设置
stdio参数,让子进程的stdout/stderr通过管道传递给父进程,不会直接输出到终端;同时忽略子进程的stdin,避免不必要的输入交互。 - 优雅终止:先尝试用
SIGTERM信号让子进程优雅退出,超时后用SIGKILL强制杀死,保证子进程能被彻底终止。
内容的提问来源于stack exchange,提问作者johann1301s
相关产品推荐
相关产品推荐

