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

Python如何在收到SIGKILL前检测系统重启?

解决方案

针对启动脚本直接发送SIGKILL导致无法优雅处理的问题,你可以尝试以下几种方法提前检测系统重启/关机事件:

1. 监听systemd关机事件(适用于使用systemd的Linux系统)

多数现代Linux系统用systemd管理关机流程,系统关机前会创建/run/systemd/shutdown/scheduled文件,你可以用后台线程定时检查这个文件的存在,一旦检测到就立即执行持久化和第三方服务断开逻辑:

import os
import time
from threading import Thread

def handle_shutdown():
    # 替换为你的数据持久化和服务断开逻辑
    print("执行优雅关闭:保存数据并断开第三方服务...")
    # save_collected_data()
    # disconnect_third_party_services()

def monitor_shutdown_signal():
    shutdown_trigger = "/run/systemd/shutdown/scheduled"
    while True:
        if os.path.exists(shutdown_trigger):
            handle_shutdown()
            break
        time.sleep(1)

# 脚本启动时启动监控线程
Thread(target=monitor_shutdown_signal, daemon=True).start()

也可以通过dbus直接监听systemd的关机信号,但需要依赖dbus-python库,实现相对复杂,文件检查的方式更轻量。

2. 脱离启动脚本的进程组

如果启动脚本是通过进程组发送SIGKILL(比如kill -KILL -$PARENT_PGID),你可以在Python脚本启动时主动脱离原进程组,避免被误杀:

import os

# 启动时将自身放入新的进程组,脱离父进程的进程组控制
os.setpgrp()

这样启动脚本发送的组信号不会影响到你的脚本,之后你可以正常监听SIGTERM信号,或者用上述的systemd监控方法完成优雅处理。

3. 监控父进程状态

你的脚本的父进程是那个启动脚本,你可以定时检查父进程的状态,一旦发现父进程进入停止/僵尸状态,或者直接退出,就立即执行优雅处理:

import os
import psutil
import time
from threading import Thread

def handle_shutdown():
    print("执行优雅关闭:保存数据并断开第三方服务...")
    # save_collected_data()
    # disconnect_third_party_services()

def monitor_parent_process():
    parent_pid = os.getppid()
    while True:
        try:
            parent_proc = psutil.Process(parent_pid)
            # 检查父进程是否处于停止或僵尸状态
            if parent_proc.status() in (psutil.STATUS_STOPPED, psutil.STATUS_ZOMBIE):
                handle_shutdown()
                break
        except psutil.NoSuchProcess:
            # 父进程已退出,触发优雅处理
            handle_shutdown()
            break
        time.sleep(1)

Thread(target=monitor_parent_process, daemon=True).start()

这个方法需要安装psutil库,如果系统允许安装第三方库可以使用。

4. 检查系统运行状态

通过系统命令直接查询当前系统是否处于关机/重启状态,比如用systemctl:

import subprocess
import time
from threading import Thread

def handle_shutdown():
    print("执行优雅关闭:保存数据并断开第三方服务...")
    # save_collected_data()
    # disconnect_third_party_services()

def check_system_state():
    while True:
        try:
            # 查询系统运行状态
            result = subprocess.run(
                ["systemctl", "is-system-running"],
                capture_output=True,
                text=True,
                timeout=2
            )
            status = result.stdout.strip()
            if status in ("stopping", "rebooting"):
                handle_shutdown()
                break
        except (subprocess.CalledProcessError, subprocess.TimeoutExpired):
            # 兼容无systemctl的系统,可替换为其他检测逻辑
            pass
        time.sleep(2)

Thread(target=check_system_state, daemon=True).start()

这些方法的优先级推荐:进程组脱离 > systemd文件监控 > 父进程状态监控,具体选择取决于你的系统环境和启动脚本的行为逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 12:37:27