You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Windows Server 2019下实现指定前缀服务CPU占用≥20%时自动重启的批处理方案咨询

Windows Server 2019下实现指定前缀服务CPU占用≥20%时自动重启的批处理方案咨询

嗨,我来帮你解决这个棘手的问题!你遇到的这种服务无明确日志中断、CPU占高却完全不干活的情况确实闹心,临时用自动重启来兜底过渡,等和开发者找到根本原因是个务实的办法。结合Windows Server 2019的环境,我给你整理了一套可行的方案,用PowerShell配合任务计划来实现每分钟检查并自动重启:

一、核心思路

批处理原生处理进程CPU占用和服务关联比较繁琐,所以我们用PowerShell来做核心判断逻辑——它能方便地获取进程CPU数据、关联对应的服务,再执行重启操作;如果你习惯用批处理,也可以让批处理调用PowerShell脚本,或者直接用PowerShell脚本作为执行主体。

二、具体实现脚本

方案1:纯PowerShell脚本(推荐,更灵活)

创建一个RestartHighCpuService.ps1文件,内容如下(记得替换配置参数里的占位内容):

# 配置参数,根据你的实际情况修改
$servicePrefix = "你的服务前缀" # 比如你的进程名是"EServiceXXX",这里填"EService"
$cpuThreshold = 20 # CPU占用阈值(百分比)
$logPath = "C:\ServiceRestartLog.txt" # 日志文件路径,方便后续排查问题
$coolDownMinutes = 5 # 冷却时间,避免重启后立刻再次触发(可选)

# 获取当前时间,用于日志记录
$currentTime = Get-Date -Format "yyyy-MM-dd HH:mm:ss"

# 检查冷却时间内是否已经重启过,防止频繁重启
$lastRestart = Get-Content $logPath -ErrorAction SilentlyContinue | Select-String "已重启服务" | Select-Object -Last 1
if ($lastRestart) {
    $restartTime = [DateTime]::Parse($lastRestart.ToString().Split(" ")[0..1] -join " ")
    if ((New-TimeSpan -Start $restartTime -End $currentTime).TotalMinutes -lt $coolDownMinutes) {
        Add-Content $logPath "$currentTime - 处于冷却期,跳过本次检查"
        exit
    }
}

# 获取匹配前缀的进程
$targetProcesses = Get-Process -Name "$servicePrefix*" -ErrorAction SilentlyContinue
if ($targetProcesses) {
    foreach ($proc in $targetProcesses) {
        # 通过进程ID关联对应的服务,确保重启的是正确的服务
        $service = Get-CimInstance Win32_Service | Where-Object { $_.ProcessId -eq $proc.Id }
        if ($service) {
            # 计算当前CPU占用率(累计CPU时间/运行总时间*100,比瞬时值更准确)
            $runTimeSeconds = (Get-Date - $proc.StartTime).TotalSeconds
            $cpuUsage = if ($runTimeSeconds -gt 0) { $proc.CPU / $runTimeSeconds * 100 } else { 0 }
            
            if ($cpuUsage -ge $cpuThreshold) {
                Add-Content $logPath "$currentTime - 检测到服务[$($service.Name)]对应的进程[$($proc.Name)]CPU占用率为[$([math]::Round($cpuUsage,2))%],超过阈值[$cpuThreshold%],开始重启"
                # 强制重启服务
                Restart-Service -Name $service.Name -Force -ErrorAction Stop
                Add-Content $logPath "$currentTime - 服务[$($service.Name)]已重启完成"
            } else {
                Add-Content $logPath "$currentTime - 服务[$($service.Name)]对应的进程[$($proc.Name)]CPU占用率为[$([math]::Round($cpuUsage,2))%],低于阈值,无需操作"
            }
        } else {
            Add-Content $logPath "$currentTime - 进程[$($proc.Name)]未关联到任何服务,跳过检查"
        }
    }
} else {
    Add-Content $logPath "$currentTime - 未找到前缀为[$servicePrefix]的进程"
}

方案2:批处理调用PowerShell脚本

如果你更习惯用批处理,创建一个CheckAndRestartService.bat文件,内容如下:

@echo off
:: 配置参数,和PowerShell脚本对应
set "servicePrefix=你的服务前缀"
set "cpuThreshold=20"
set "logPath=C:\ServiceRestartLog.txt"
set "coolDownMinutes=5"

:: 调用PowerShell执行逻辑,注意替换脚本的实际路径
powershell -ExecutionPolicy Bypass -File "C:\你的脚本存放路径\RestartHighCpuService.ps1" -servicePrefix "%servicePrefix%" -cpuThreshold %cpuThreshold% -logPath "%logPath%" -coolDownMinutes %coolDownMinutes%

三、关键细节说明

  • CPU占用计算:用进程累计CPU时间除以运行总时间来计算百分比,比直接取瞬时值更稳定,避免因为系统波动误判。
  • 服务关联:通过进程ID匹配对应的服务,确保我们重启的是目标服务,而不是同名的无关进程。
  • 冷却时间:防止服务重启后因为初始化等原因CPU暂时冲高,导致立刻再次重启,影响业务稳定性。

四、设置任务计划程序

  1. 打开「任务计划程序」,点击「创建基本任务」。
  2. 名称填“监控并重启高CPU服务”,描述按需填写,点击下一步。
  3. 触发条件选择「每天」,然后设置重复任务间隔为1分钟,持续时间选「无限期」,点击下一步。
  4. 操作选择「启动程序」:
    • 如果用纯PowerShell脚本,程序或脚本选powershell.exe,参数填-ExecutionPolicy Bypass -File "C:\你的脚本路径\RestartHighCpuService.ps1"
    • 如果用批处理,直接选择批处理文件的路径。
  5. 勾选「使用最高权限运行」(重启服务需要管理员权限),点击完成。

五、注意事项

  • 先手动执行脚本测试,确认能正确识别进程、计算CPU占用、重启服务,同时检查日志文件是否正常记录。
  • 如果你的服务对应多个进程,脚本会分别检查每个进程的CPU占用,只要有一个达到阈值就重启服务,你可以根据实际情况调整逻辑。
  • 定期清理日志文件,避免占用过多磁盘空间。

备注:内容来源于stack exchange,提问作者Mohammed Esam

火山引擎 最新活动