如何通过npm脚本优雅停止NodeJS进程适配Cypress E2E测试场景
解决方案
你之前尝试的kill -SIGINT %1不生效,是因为%1是Windows批处理的入参语法,npm脚本执行时不会自动把后台服务的进程ID传递给stop脚本,所以取不到目标进程号,自然无法终止进程。下面提供两种可行方案:
方案1:类Unix(Mac/Linux)环境快速适配
不需要额外安装依赖,通过临时文件存储服务进程ID实现终止:
{ "start": "node dist/server", "test:e2e": "ng e2e", "stop": "kill -SIGINT $(cat .server.pid) && rm -f .server.pid", "cypress:e2e": "npm run start & echo $! > .server.pid && wait-on http://localhost:8080 && npm run test:e2e && npm run stop" }
逻辑说明:启动后台服务时,把进程PID写入.server.pid临时文件,执行stop脚本时读取该PID发送SIGINT信号,执行完成后自动删除临时文件。
方案2:跨平台通用方案(推荐)
推荐使用专门针对「启动服务-等待就绪-执行测试-自动关停」场景的工具start-server-and-test,无需自己维护进程管理逻辑,兼容全平台:
- 首先安装开发依赖:
npm i start-server-and-test -D - 调整npm脚本,不需要单独配置stop脚本:
{ "start": "node dist/server", "test:e2e": "ng e2e", "cypress:e2e": "start-server-and-test start http://localhost:8080 test:e2e" }
逻辑说明:工具会自动启动你的Node服务,等待8080端口可访问后执行E2E测试,测试执行完成(无论成功失败)会自动向Node进程发送SIGINT信号,完美适配你在server.ts中配置的SIGINT监听退出逻辑。
补充优化建议
如果偶尔还是出现进程无法退出的情况,可以优化server.ts的退出逻辑,先关闭HTTP服务再退出进程,避免端口占用残留:
const server = APP.listen(PORT, () => { logger.info( `Node application has started their node server on port ${PORT}`, ) }) process.on('SIGINT', () => { // 先关闭HTTP连接,再退出进程 server.close(() => process.exit(1)) })
内容的提问来源于stack exchange,提问作者Tarun
相关产品推荐
相关产品推荐

