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

Debian 10下如何捕获系统关机事件以实现数据持久化?

解决Debian 10系统关机前无法捕获事件保存数据的问题

问题分析

你的代码存在两个关键问题:

  • 同时混用sigaction和signal注册SIGTERM信号处理函数,后者会覆盖前者设置,导致信号处理逻辑混乱
  • proc_term仅设置退出标志,未执行实际的数据保存操作;且信号处理函数内调用的LOG_WARN如果是非异步安全函数,可能引发未定义行为

修复方案

1. 统一使用sigaction注册信号

放弃signal函数,用sigaction统一处理所有需要捕获的信号(系统关机时通常发送SIGTERM,终端中断发送SIGINT,部分场景还会发送SIGHUP):

#include <signal.h>
#include <string.h>
#include <unistd.h>

volatile sig_atomic_t need_exit = 0;

void handle_signal(int sig) {
    // 使用异步安全的方式记录信号,避免调用非安全函数
    const char *msg;
    switch(sig) {
        case SIGTERM: msg = "Received SIGTERM (shutdown/terminate)\n"; break;
        case SIGINT: msg = "Received SIGINT (interrupt)\n"; break;
        case SIGHUP: msg = "Received SIGHUP (hangup)\n"; break;
        default: msg = "Received unknown signal\n"; break;
    }
    // write是异步安全函数,直接写入标准错误输出
    write(STDERR_FILENO, msg, strlen(msg));
    
    need_exit = 1;
}

void setup_signals() {
    struct sigaction sa;
    memset(&sa, 0, sizeof(sa));
    sa.sa_handler = handle_signal;
    // 阻塞所有信号,避免处理信号时被其他信号打断
    sigfillset(&sa.sa_mask);
    
    // 注册需要捕获的信号
    sigaction(SIGTERM, &sa, NULL);
    sigaction(SIGINT, &sa, NULL);
    sigaction(SIGHUP, &sa, NULL);
}

2. 主程序检测退出标志并执行保存

在主循环中定期检查need_exit标志,一旦触发就执行数据保存并退出:

#include <unistd.h>

// 假设你有这个数据保存函数,需保证逻辑同步、无副作用
void save_data_to_file();

int main() {
    setup_signals();
    
    while(!need_exit) {
        // 你的业务逻辑代码
        sleep(1);
    }
    
    // 执行数据保存操作
    save_data_to_file();
    return 0;
}

3. systemd服务额外配置(若应用由systemd管理)

Debian 10默认使用systemd,若你的应用通过systemd管理,需修改服务文件(如/etc/systemd/system/your-app.service),确保systemd给足进程退出时间:

[Service]
ExecStart=/path/to/your/application
# 让systemd等待进程主动退出,而非直接强制杀死
KillMode=process
# 设置关机时等待进程退出的超时时间(根据保存逻辑调整时长)
TimeoutStopSec=30s
# 禁止超时后发送SIGKILL,保证进程有机会完成保存
SendSIGKILL=no

修改后执行systemctl daemon-reload && systemctl restart your-app.service生效。

关键注意事项

  • 信号处理函数必须是异步安全的:不能调用malloc、printf、非异步安全的日志函数等,仅能使用POSIX定义的异步安全函数(如write、_exit等)
  • 数据保存函数要保证原子性,可先写入临时文件,完成后再替换目标文件,避免关机时写入一半导致文件损坏

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 04:55:29