Created
July 6, 2026 06:12
-
-
Save rampageX/75093d4b52acbf850be7c4c1aa19d238 to your computer and use it in GitHub Desktop.
Windows 多服务强制重启监控
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| @echo off | |
| setlocal enabledelayedexpansion | |
| :: ==================================================================== | |
| :: 多服务强制重启监控(增强版) | |
| :: 兼容:Windows Server 2008 中文系统 | |
| :: 功能: | |
| :: 1. Stop Pending 超时自动强杀 | |
| :: 2. 自动识别服务 EXE | |
| :: 3. SYSTEM 权限 taskkill(需 PsExec) | |
| :: ==================================================================== | |
| :: ====== 配置服务名列表 ====== | |
| set serviceList=Spooler RapService | |
| :: ====== 参数 ====== | |
| set maxRetries=3 | |
| set retryDelay=10 | |
| set stopTimeout=30 | |
| set pendingThreshold=10 | |
| :: ====== 日志 ====== | |
| for %%F in ("%~nx0") do set scriptName=%%~nF | |
| set log=%~dp0%scriptName%.log | |
| call :log "多服务强制重启监控启动" | |
| :: ====== 主循环 ====== | |
| for %%S in (%serviceList%) do ( | |
| set svcname=%%S | |
| set tryCount=0 | |
| call :log "" | |
| call :log "开始处理服务 [!svcname!]" | |
| :retry_loop_%%S | |
| set /a tryCount+=1 | |
| call :log "尝试停止服务 [!svcname!]..." | |
| net stop "!svcname!" >> %log% 2>&1 | |
| :: ===== 等待停止(增强版)===== | |
| set waitTime=0 | |
| set pendingTime=0 | |
| :wait_stop_%%S | |
| set state= | |
| for /f "tokens=3 delims=: " %%a in ('sc query "!svcname!" ^| findstr "STATE"') do set state=%%a | |
| if /i "!state!"=="STOPPED" ( | |
| call :log "服务 [!svcname!] 成功停止" | |
| goto start_service_%%S | |
| ) | |
| if /i "!state!"=="STOP_PENDING" ( | |
| set /a pendingTime+=1 | |
| ) else ( | |
| set pendingTime=0 | |
| ) | |
| set /a waitTime+=1 | |
| if !pendingTime! GEQ %pendingThreshold% ( | |
| call :log "服务 [!svcname!] 长时间 STOP_PENDING,强制终止" | |
| goto force_kill_%%S | |
| ) | |
| if !waitTime! GEQ %stopTimeout% ( | |
| call :log "服务 [!svcname!] 停止超时" | |
| goto force_kill_%%S | |
| ) | |
| timeout /t 1 /nobreak >nul | |
| goto wait_stop_%%S | |
| :start_service_%%S | |
| call :log "尝试启动服务 [!svcname!]..." | |
| net start "!svcname!" >> %log% 2>&1 | |
| timeout /t %retryDelay% /nobreak >nul | |
| set state= | |
| for /f "tokens=3 delims=: " %%a in ('sc query "!svcname!" ^| findstr "STATE"') do set state=%%a | |
| if /i not "!state!"=="RUNNING" ( | |
| call :log "服务 [!svcname!] 第 !tryCount! 次启动失败" | |
| if !tryCount! GEQ %maxRetries% ( | |
| call :log "服务 [!svcname!] 重启失败超过 %maxRetries% 次,准备重启服务器" | |
| goto reboot_server | |
| ) else ( | |
| call :log "等待 %retryDelay% 秒后重试..." | |
| timeout /t %retryDelay% /nobreak >nul | |
| goto retry_loop_%%S | |
| ) | |
| ) else ( | |
| call :log "服务 [!svcname!] 启动成功" | |
| ) | |
| call :log "服务 [!svcname!] 处理完成" | |
| ) | |
| call :log "多服务强制重启监控结束" | |
| goto end | |
| :: ====== 强制杀进程(增强版)====== | |
| :force_kill_%%S | |
| call :get_exe_name "!svcname!" | |
| call :log "检测到服务进程名: !exeName!" | |
| :: 杀 PID | |
| for /f "tokens=2 delims=:" %%a in ('sc queryex "!svcname!" ^| findstr "PID"') do set pid=%%a | |
| set pid=!pid: =! | |
| if not "!pid!"=="" ( | |
| call :log "SYSTEM 权限 taskkill PID !pid!" | |
| psexec -accepteula -s -d taskkill /PID !pid! /F >> %log% 2>&1 | |
| ) else ( | |
| call :log "未获取到 PID" | |
| ) | |
| :: 按 EXE 名兜底 | |
| if not "!exeName!"=="" ( | |
| call :log "SYSTEM 权限 taskkill !exeName!" | |
| psexec -accepteula -s -d taskkill /IM "!exeName!" /F >> %log% 2>&1 | |
| ) else ( | |
| call :log "未获取 EXE 名" | |
| ) | |
| timeout /t 3 /nobreak >nul | |
| goto retry_loop_%%S | |
| :: ====== 获取 EXE 名 ====== | |
| :get_exe_name | |
| setlocal enabledelayedexpansion | |
| set exeName= | |
| set fullpath= | |
| for /f "tokens=2,* delims=:" %%a in ('sc qc "%~1" ^| findstr /i "BINARY_PATH_NAME"') do ( | |
| set fullpath=%%b | |
| ) | |
| if defined fullpath ( | |
| set fullpath=!fullpath:~1! | |
| for %%f in ("!fullpath!") do set exeName=%%~nxf | |
| ) | |
| endlocal & set exeName=%exeName% | |
| goto :eof | |
| :: ====== 重启服务器 ====== | |
| :reboot_server | |
| call :log "等待 30 秒后重启服务器" | |
| echo 30 秒后重启服务器 | |
| @rem timeout /t 30 /nobreak >nul | |
| @rem shutdown /r /f /t 0 | |
| goto end | |
| :: ====== 日志函数 ====== | |
| :log | |
| setlocal enabledelayedexpansion | |
| for /f "tokens=1-2 delims=." %%a in ("%time%") do set logtime=%%a | |
| echo === [%date% !logtime!] %~1 >> %log% | |
| endlocal & goto :eof | |
| :end | |
| endlocal |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment