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

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');
});

关键修复点

  1. 阻止进程立即退出:通过e.preventDefault()阻止Node的默认终止行为,给异步写入操作留足执行时间。
  2. 手动控制退出时机:在await writeFile完成后调用process.exit(),确保文件写入成功后再结束进程。
  3. 路径与目录处理:使用绝对路径避免相对路径解析错误,提前创建配置目录防止写入失败。
  4. 错误捕获与统一逻辑:封装退出处理函数减少重复代码,添加错误捕获便于排查问题。

Windows额外注意

如果e.preventDefault()不生效,可在监听函数开头添加process.stdin.resume(),保持进程存活直到异步操作完成。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 00:25:53