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

使用inquirer和child_process开发的CLI按CTRL+C无法退出全部进程怎么办

解决方案

问题根源

问题是两个原因共同导致的:

  • execSync运行的npm run start会生成嵌套子进程,Node.js默认不会将CTRL+C触发的SIGINT信号转发给这些子进程,主进程退出后子进程变成孤儿进程在后台持续运行
  • inquirer在进程异常退出时没有正常还原终端TTY的交互状态,导致终端无响应

修改后的完整代码

const inquirer = require('inquirer')
const { spawn } = require('child_process')
const { readdirSync } = require('fs')

const targetFolder = './src/pages'
const directories = readdirSync(targetFolder)
let childProcess = null

// 监听CTRL+C信号,主动清理子进程后退出
process.on('SIGINT', () => {
  if (childProcess) {
    // 杀死整个子进程树
    process.kill(-childProcess.pid)
  }
  process.exit(0)
})

const questions = [
    {
        type: 'list',
        name: 'page',
        message: 'Choose page to compile',
        choices: directories,
    },
]

inquirer.prompt(questions).then(({ page }) => {
    // 用spawn替代execSync,方便管理子进程实例
    childProcess = spawn('npm', ['run', 'start', '--', '--env', `page=${page}`], {
        stdio: 'inherit',
        // 类Unix系统下创建新进程组,方便一次性杀死所有嵌套的子进程
        detached: process.platform !== 'win32'
    })

    // 子进程退出后主进程同步退出
    childProcess.on('exit', (code) => {
        process.exit(code)
    })
})

关键改动说明

  • 把同步的execSync换成异步的spawn,可以拿到子进程实例做后续管理
  • 添加SIGINT信号监听,收到CTRL+C信号时主动杀死整个子进程树,再退出主进程
  • 类Unix系统下开启detached配置,创建独立进程组,方便一次性杀死所有嵌套的子进程
  • 子进程退出后主进程同步退出,避免遗留进程

跨平台兼容说明

如果需要兼容Windows系统,建议安装cross-spawn包替换原生的child_process.spawn,可以自动处理Windows下npm执行路径和进程杀死的兼容问题,安装命令为npm i cross-spawn,之后把代码里的const { spawn } = require('child_process')替换为const spawn = require('cross-spawn')即可。


内容的提问来源于stack exchange,提问作者Hanzo Hattori

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 10:18:03