AWS Batch作业中NodeJS无法捕获SIGTERM信号问题求助
问题:AWS Batch中Node.js进程无法捕获SIGTERM信号
我尝试捕获AWS在回收SPOT实例或作业超时前发送的SIGTERM信号,但注册的处理函数始终未执行,看不到对应日志。日志里只显示npm因SIGTERM命令失败。测试代码里设置了SIGTERM信号监听、40分钟sleep,并且把AWS Batch作业超时设为5分钟来触发场景,但处理函数内的日志从来没出现过。
测试代码
process.on('SIGTERM', () => { Logger.info('Application received SIGTERM signal'); process.exit(0); } const executeJob = async () => { await sleep(40 * 60 * 1000); } executeJob();
此前测试的简化代码
process.on('SIGTERM', () => console.log('test SIGNTERM'))
日志报错信息
npm ERR! path / npm ERR! command failed npm ERR! signal SIGTERM npm ERR! command sh -c -- NODE_ENV=dev npx babel-node --presets @babel/preset-env src/functions/entries.js npm ERR! A complete log of this run can be found in: npm ERR! /root/.npm/_logs/2023-09-27T17_54_18_152Z-debug-0.log
解决方案
问题核心在于:SIGTERM信号被shell进程拦截,没有传递给你的Node.js应用进程。
当你通过npm run或sh -c这类命令启动应用时,实际运行的是一个shell父进程,你的Node.js进程是它的子进程。AWS发送的SIGTERM会先被shell进程接收,而shell默认不会将信号转发给子进程,直接退出后会强制终止子进程,导致你的Node.js应用根本没机会执行信号处理函数。
可采用以下几种解决方式:
- 直接启动Node.js进程:跳过npm、npx的shell包装,将Batch作业命令改为直接调用编译后的Node.js文件,比如
node dist/entries.js。 - 用exec替换shell进程:在package.json的启动脚本中加入
exec命令,示例:"scripts": { "start": "exec NODE_ENV=dev npx babel-node --presets @babel/preset-env src/functions/entries.js" }exec会让Node.js进程直接替换shell进程,这样SIGTERM信号会直接发送给你的应用。 - 检查代码语法:你的测试代码中
process.on('SIGTERM', () => { ... }缺少闭合的),虽然日志显示进程已启动,但语法错误可能导致信号监听逻辑失效,建议修复。
内容的提问来源于stack exchange,提问作者Rafael de Carvalho
相关产品推荐
相关产品推荐

