You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 07:33:52