Node.js信号处理器失效:仅执行首行代码,无法保存配置
SIGINT信号触发时无法保存config到文件的解决方案
问题重现
原代码
process.on('SIGINT', ExitHandler); process.on('SIGTERM', ExitHandler); process.on('SIGQUIT', ExitHandler); async function ExitHandler() { console.log('ctrl+c'); await writeFile('./config/user.json', JSON.stringify(config)); }
相关信息
- 目标config内容:
{ "984620726436921364": { "SaveAllImage": { "convert": false }, "Screenshot": { "format": "webp" } } }
- 实际结果:按下Ctrl+C后,终端打印
ctrl+c,但生成的./config/user.json内容为{} - 环境:npm 9.1.3,pnpm 7.25.0,Node.js 19.4.0,Windows 11 25276.1000
问题原因
Node.js收到SIGINT这类终止信号时,默认会立即终止进程,不会等待异步操作(比如await writeFile)完成。另外原代码未处理进程退出时机,也没确保config变量作用域正确、目标目录存在。
修复方案
修正后的代码
import { writeFile, mkdir } from 'fs/promises'; import { existsSync } from 'fs'; import path from 'path'; // 用绝对路径避免工作目录解析问题 const configPath = path.resolve(__dirname, './config/user.json'); const configDir = path.dirname(configPath); // 提前创建配置目录,防止写入失败 if (!existsSync(configDir)) { await mkdir(configDir, { recursive: true }); } // 统一退出处理逻辑 async function handleExit(signal) { console.log(`收到${signal}信号`); try { // 写入配置并格式化,方便后续查看 await writeFile(configPath, JSON.stringify(config, null, 2)); console.log('配置已成功保存'); process.exit(0); // 操作完成后正常退出 } catch (err) { console.error('保存配置失败:', err); process.exit(1); // 保存失败时异常退出 } } // 绑定信号监听,阻止默认立即退出行为 process.on('SIGINT', async (e) => { e.preventDefault(); await handleExit('SIGINT'); }); process.on('SIGTERM', async (e) => { e.preventDefault(); await handleExit('SIGTERM'); }); process.on('SIGQUIT', async (e) => { e.preventDefault(); await handleExit('SIGQUIT'); });
关键修复点
- 阻止进程立即退出:通过
e.preventDefault()阻止Node的默认终止行为,给异步写入操作留足执行时间。 - 手动控制退出时机:在
await writeFile完成后调用process.exit(),确保文件写入成功后再结束进程。 - 路径与目录处理:使用绝对路径避免相对路径解析错误,提前创建配置目录防止写入失败。
- 错误捕获与统一逻辑:封装退出处理函数减少重复代码,添加错误捕获便于排查问题。
Windows额外注意
如果e.preventDefault()不生效,可在监听函数开头添加process.stdin.resume(),保持进程存活直到异步操作完成。
内容的提问来源于stack exchange,提问作者MoMuAlt
相关产品推荐
相关产品推荐

