Node.js使用forever运行时如何捕获SIGINT/SIGKILL信号执行退出前清理
问题根因分析
- 信号监听不全面:默认情况下forever停止进程时发送的是
SIGTERM信号,而非你仅监听的SIGINT;且SIGKILL是系统级强制终止信号,任何程序都无法捕获,监听该信号完全无效。 - 路径匹配错误:你使用相对路径写入状态文件,实际写入路径是forever进程的工作目录,而非Node.js脚本所在目录,容易出现找不到文件的误判,也可能存在权限不足写入失败的问题。
- forever参数使用误区:
forever stop后应传入forever管理的任务ID、脚本名或forever生成的pid文件路径,直接传系统级pid可能导致信号发送逻辑异常。
解决方案
第一步:修正Node.js代码逻辑
const WebsocketServer = require("websocket").server const jsonfile = require("jsonfile") const path = require("path") // 覆盖所有可捕获的常规终止信号 const exitSignals = ['SIGINT', 'SIGTERM', 'SIGHUP', 'SIGQUIT'] exitSignals.forEach(signal => { process.on(signal, () => { console.log(`${signal} fired, writing last state`) try { // 用绝对路径写入,避免相对路径的目录偏差 const statePath = path.join(__dirname, "./someLastState.json") jsonfile.writeFileSync(statePath, states) // 确保文件写入完成后显式退出进程 process.exit(0) } catch (err) { // 错误会被forever记录到指定的错误日志eIoT1.log中 console.error("Write state failed:", err) process.exit(1) } }) }) // 原有websocket服务逻辑保持不变 ...
第二步:调整forever启停操作
- 先验证代码本身有效性:直接运行
node IoT1.js,按Ctrl+C发送SIGINT,确认控制台有对应输出、脚本所在目录正常生成状态文件,排除代码逻辑问题。 - 启动forever任务时显式指定工作目录和默认kill信号:
# 先停掉所有原有相关任务,避免冲突 forever stopall # 把/path/to/your/script替换为你IoT1.js所在的实际目录 forever start -p /path/to/your/script -l lIoT1.log -e eIoT1.log -c node --killSignal=SIGTERM IoT1.js
- 停止任务时使用forever管理的脚本名操作,不要传系统级pid:
forever stop IoT1.js
第三步:结果验证
停止任务后分别检查对应文件:
- 查看lIoT1.log是否有信号触发的日志输出
- 查看IoT1.js所在目录下是否生成了someLastState.json文件
内容的提问来源于stack exchange,提问作者quanguyen
相关产品推荐
相关产品推荐

