Windows Server补丁需滚动更新而非全量推送,因IIS、SQL Server等服务对KB累积更新敏感,易致0x80070643失败或w3svc重启;须禁用自动重启、逐节点安装验证、NLB摘机延时、应用池预停、SQL补丁专项处理,并依赖PSWindowsUpdate脚本化控制全流程。
Windows Server 补丁更新为什么不能直接全量推送
因为生产环境的 iis、sql server、.net 运行时等服务对补丁敏感,kb5004237 这类累积更新可能触发 0x80070643 安装失败,或导致 w3svc 意外重启。滚动更新不是为了“更酷”,而是避免单点故障扩散——你没法接受所有 web 服务器在同一分钟内蓝屏。
- 关键原则:每次只更新一个节点,验证通过后再推进下一个
- 必须关闭自动重启策略,用
Set-ItemProperty手动控制HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU下的NoAutoRebootWithLoggedOnUsers和AUOptions - 补丁安装前检查
Get-WindowsUpdateLog输出中是否有0x8024A105(依赖缺失)或0x80070005(权限不足) - SQL Server 实例所在机器要额外确认
setup.exe /action=patch是否已由 SQL Server 安装中心预载,否则PSWindowsUpdate模块会跳过 SQL 相关补丁
用 PSWindowsUpdate 模块实现可控滚动更新
别碰 GUI 界面或 WSUS 控制台做滚动——它们不暴露节点级执行顺序和回滚钩子。PSWindowsUpdate 是目前唯一能脚本化控制「下载→安装→静默重启→等待服务就绪」全流程的方案,但默认行为危险,必须重写逻辑。
- 先用
Install-Module PSWindowsUpdate -Force -SkipPublisherCheck安装模块(PowerShell 5.1+ 环境) - 禁用默认自动重启:
Get-WUServiceManager | Where-Object {$_.ServiceID -eq '7971f918-a847-4430-9f79-f0789f08115d'} | Remove-WUServiceManager,否则Install-WindowsUpdate会绕过你的控制 - 逐台执行时,用
Invoke-Command -ComputerName $server -ScriptBlock { Install-WindowsUpdate -AcceptAll -IgnoreReboot },并配合Test-NetConnection $server -Port 443和Get-Service w3svc | Where-Object Status -eq 'Running'做就绪判断 - 注意
Install-WindowsUpdate的-KBArticleID参数只支持单个 KB 号,批量指定要用数组传参,否则静默跳过
滚动窗口期间如何防止负载倾斜失效
如果你用 NLB 或 Windows 负载均衡器,Enable-NlbClusterNode 和 Disable-NlbClusterNode 不是原子操作——节点从禁用到真正退出流量转发有 3–8 秒延迟,这期间新连接仍可能打进来。
- 在补丁前执行
Disable-NlbClusterNode -HostName $server -Force后,必须跟Start-Sleep -Seconds 10,再确认Get-NlbClusterNode -HostName $server返回状态为Draining - IIS 应用程序池要提前设为
AutoStart=False,并在补丁完成后用Start-WebAppPool显式拉起,避免热启动失败被忽略 - 若使用 Azure Load Balancer 或 F5,不能依赖 Windows 自带 NLB 命令,得调用对应 REST API 或
az network lb address-pool update动态摘除后端池 - 验证阶段至少采集两个指标:HTTP 200 响应率(用
Invoke-RestMethod轮询)、以及Get-Counter '\ASP.NET Applications(*)\Requests/Sec'是否恢复基线值
回滚失败补丁的实操底线
补丁失败后想“一键还原”?Windows 没有真正的事务式回滚。所谓卸载,只是调用 wusa /uninstall /kb:5004237 卸载更新包,但无法恢复被覆盖的 DLL 签名或注册表键值——尤其当 .NET Framework 4.8 更新失败时,dotnet --list-runtimes 可能显示混乱版本。
- 滚动更新前必须对系统盘做
wbadmin start backup快照,且验证Get-WBBackupSet中BackupTarget可读 - 卸载失败补丁时,先停掉所有依赖服务:
Stop-Service w3svc, MSSQLSERVER, W3SVC,否则wusa会返回0x80070422 - 如果
Get-HotFix | Where-Object HotFixID -eq 'KB5004237'查不到记录,说明补丁根本没写入系统,此时不要尝试卸载,应查C:\Windows\Logs\CBS\CBS.log中最近 100 行的0x80073712错误定位组件存储损坏 - 最坏情况需用
DISM /Online /Cleanup-Image /RestoreHealth修复,但该命令会中断所有 Windows Update 操作长达 20 分钟以上,必须安排在维护窗口内
滚动更新真正的复杂点不在命令怎么敲,而在于你得同时盯住三件事:NLB 节点状态是否真实退出、IIS 应用池是否完成冷启动、SQL Server Agent 是否恢复作业调度——任何一个环节卡在“半中间”,监控就失效了。

















