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

如何实现异常挂起的Python脚本自动重启保障业务连续运行

PowerShell环境下Python脚本挂起自动重启落地方案

方案1:PowerShell原生守护(最快落地,零额外依赖)

这个方案不需要重构现有业务代码,仅需要在Python脚本主逻辑里加2行心跳上报,再配一个常驻的PowerShell守护脚本即可,适合快速上线解决当前停机问题。
核心逻辑:

  • 为每个Python业务脚本分配独立的心跳文件,要求脚本每完成一轮业务处理/每固定间隔(比如30秒),就更新对应心跳文件的时间戳
  • 守护脚本按固定频率轮询两个状态:一是对应Python进程是否存活,二是心跳文件最后更新时间是否超过预设阈值
  • 判定进程消失/心跳超时(即挂起)时,先强制终止残留的无响应进程,再重新拉起脚本,所有操作写入本地日志留痕

可直接复用的PowerShell守护脚本示例:

<# 单脚本配置项,多脚本部署时复制整段配置、修改参数即可 #>
$config = @{
    ScriptName   = "file_detect_prod.py"
    WorkDir      = "D:\prod_py_scripts\"
    PythonPath   = "C:\Python310\python.exe"
    HeartbeatFile= "D:\py_heartbeat\file_detect_lastbeat.txt"
    HangThreshold= 180  # 超过3分钟无心跳判定为挂起,根据业务实际处理时长调整
    LogFile      = "D:\py_logs\daemon_running.log"
}

while ($true) {
    $currentTime = Get-Date
    $runProc = Get-Process python -ErrorAction SilentlyContinue | Where-Object {
        $_.CommandLine -like "*$($config.ScriptName)*"
    }
    $needRestart = $false

    if (-not $runProc) {
        Add-Content $config.LogFile "[$currentTime] 进程$($config.ScriptName)不存在,触发重启"
        $needRestart = $true
    } else {
        if (Test-Path $config.HeartbeatFile) {
            $lastBeatTime = (Get-Item $config.HeartbeatFile).LastWriteTime
            $timeDiff = ($currentTime - $lastBeatTime).TotalSeconds
            if ($timeDiff -gt $config.HangThreshold) {
                Add-Content $config.LogFile "[$currentTime] 进程$($config.ScriptName)心跳超时$timeDiff秒,判定挂起,触发重启"
                Stop-Process -Id $runProc.Id -Force
                Start-Sleep 2
                $needRestart = $true
            }
        } else {
            Add-Content $config.LogFile "[$currentTime] 进程$($config.ScriptName)心跳文件丢失,触发重启"
            Stop-Process -Id $runProc.Id -Force
            $needRestart = $true
        }
    }

    if ($needRestart) {
        Start-Process -FilePath $config.PythonPath -ArgumentList $config.ScriptName -WorkingDirectory $config.WorkDir -WindowStyle Hidden
        Add-Content $config.LogFile "[$currentTime] 进程$($config.ScriptName)重启完成"
    }

    Start-Sleep 60 # 每1分钟巡检一次
}

Python侧需要加的心跳代码,直接塞到主业务循环里就行,不碰核心逻辑:

import time
# 心跳路径和守护脚本里的配置保持一致
HEARTBEAT_PATH = r"D:\py_heartbeat\file_detect_lastbeat.txt"

# 你的原有主逻辑
while True:
    # 检测新增文件、处理数据、写MySQL的原有代码
    # xxx

    # 每轮处理完更新心跳
    with open(HEARTBEAT_PATH, "w", encoding="utf-8") as f:
        f.write(str(time.time()))
    time.sleep(1) # 原有轮询间隔

如果遇到单文件处理耗时较长的场景,可以把心跳更新逻辑拆到单独的守护线程里,固定间隔更新,避免处理大文件时被误判为挂起。

方案2:Python进程自托管(不需要单独维护PowerShell脚本)

如果不想额外跑一个PowerShell守护脚本,可以写一个统一的Python入口,用子进程模式托管业务脚本:

  • 入口脚本用subprocess.Popen拉起业务脚本
  • 主进程持续监听子进程状态,同时通过心跳文件/管道通信检测子进程是否响应
  • 判定子进程退出/挂起时,杀掉残留子进程后重新拉起
  • 可额外配置重启冷却规则:比如10分钟内连续重启超过5次,就停止重启并写错误日志,避免脚本死循环崩溃占满资源

方案3:Windows服务化托管(生产环境长期运行推荐)

如果要覆盖服务器崩溃重启的场景,推荐把脚本封装成Windows系统服务:

  • 用服务封装工具把每个Python脚本注册为系统服务,设置启动类型为自动,服务器开机后不需要登录就会自动拉起脚本
  • 配置服务失败恢复规则:服务异常退出后自动重启,设置合适的重启延迟
  • 搭配前面提到的心跳检测逻辑,补充服务自带的进程存活检测无法识别的假死挂起场景
  • 服务运行权限可以单独配置,不需要给运维账号之外的人开服务器登录权限

落地避坑要点

  • 绝对不能只靠“进程是否存在”判定脚本正常运行,绝大多数挂起场景下Python进程是存活的,但已经停止处理业务,必须加心跳类的健康度检测
  • 挂起判定阈值要根据业务实际耗时设置,比如单文件最大处理时长是4分钟,就把阈值设为6-8分钟,避免正常处理被误杀
  • 重启前必须强制结束旧进程,防止多实例同时运行导致重复写MySQL、文件重复处理的问题
  • 所有重启、异常操作必须写本地日志,记录触发原因和时间,方便后续回溯脚本挂起的根因,逐步修复业务代码的bug
  • 有条件的话可以加简单的告警逻辑,触发重启时给相关对接人发通知,方便及时跟进异常情况

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 00:57:32