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暂时冲高,导致立刻再次重启,影响业务稳定性。
四、设置任务计划程序
- 打开「任务计划程序」,点击「创建基本任务」。
- 名称填“监控并重启高CPU服务”,描述按需填写,点击下一步。
- 触发条件选择「每天」,然后设置重复任务间隔为1分钟,持续时间选「无限期」,点击下一步。
- 操作选择「启动程序」:
- 如果用纯PowerShell脚本,程序或脚本选
powershell.exe,参数填-ExecutionPolicy Bypass -File "C:\你的脚本路径\RestartHighCpuService.ps1"; - 如果用批处理,直接选择批处理文件的路径。
- 如果用纯PowerShell脚本,程序或脚本选
- 勾选「使用最高权限运行」(重启服务需要管理员权限),点击完成。
五、注意事项
- 先手动执行脚本测试,确认能正确识别进程、计算CPU占用、重启服务,同时检查日志文件是否正常记录。
- 如果你的服务对应多个进程,脚本会分别检查每个进程的CPU占用,只要有一个达到阈值就重启服务,你可以根据实际情况调整逻辑。
- 定期清理日志文件,避免占用过多磁盘空间。
备注:内容来源于stack exchange,提问作者Mohammed Esam




