Windows服务器运维中,批量检查补丁是一项高频且关键的日常工作。手动登录每台服务器查看"控制面板-程序和功能-查看已安装的更新"显然不现实,尤其是管理几十台甚至上百台服务器的时候。最高效的方式就是用PowerShell脚本批量执行,通过Get-HotFix、CIM实例查询或者调用WMI接口,快速拉取所有服务器的补丁安装状态,生成统一报告。下面我把这套方法从头到尾讲透,包括核心脚本、批量执行方式、常见坑点和进阶技巧。

为什么必须用PowerShell批量检查补丁

Windows Server的安全补丁更新直接关系到系统安全。微软每月第二个星期二发布补丁(Patch Tuesday),如果你管理的服务器没有及时打补丁,漏洞暴露风险极高。但现实是:运维人员往往不清楚哪些服务器缺了哪些补丁,哪些补丁装了但没重启,哪些补丁安装失败了。靠人工逐台检查,效率低、容易漏、还没法追溯。PowerShell脚本能在几分钟内扫描完所有目标服务器,输出结构化的结果,这是任何GUI工具都替代不了的。

核心命令:Get-HotFix的使用与局限

最基础的补丁查询命令就是Get-HotFix。在本地执行很简单,直接在PowerShell里输入Get-HotFix就能列出所有已安装的更新。但这个命令有两个明显局限:第一,它只能查已安装的补丁,无法知道哪些补丁"应该装但没装";第二,它不支持远程批量执行,需要配合Invoke-Command或者远程会话使用。所以Get-HotFix适合单机快速查看,批量场景需要升级方案。

# 单机查看已安装补丁
Get-HotFix | Sort-Object InstalledOn -Descending | Select-Object HotFixID, Description, InstalledOn

# 查看特定补丁是否安装
Get-HotFix -Id KB5034441

批量检查补丁的完整PowerShell脚本

下面这段脚本是实战中最常用的版本。它支持从文本文件读取服务器列表,远程连接每台服务器查询补丁状态,最后导出CSV报告。你可以根据需要修改补丁KB编号来做定向检查。

# 定义目标服务器列表(从文件读取,每行一个服务器名或IP)
$servers = Get-Content "C:\Scripts\servers.txt"

# 定义要检查的关键补丁KB编号(可多个)
$targetKBs = @("KB5034441", "KB5034439", "KB5034440")

# 结果数组
$results = @()

foreach ($server in $servers) {
    try {
        Write-Host "正在检查服务器: $server ..." -ForegroundColor Cyan
        
        # 远程执行命令获取补丁信息
        $hotfixes = Invoke-Command -ComputerName $server -ScriptBlock {
            Get-HotFix | Select-Object HotFixID, Description, InstalledOn
        } -ErrorAction Stop
        
        foreach ($kb in $targetKBs) {
            $found = $hotfixes | Where-Object { $_.HotFixID -eq $kb }
            if ($found) {
                $status = "已安装"
            } else {
                $status = "未安装"
            }
            $results += [PSCustomObject]@{
                ServerName   = $server
                KBNumber     = $kb
                Status       = $status
                Description  = if ($found) { $found.Description } else { "N/A" }
                CheckedTime  = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
            }
        }
    }
    catch {
        Write-Host "无法连接服务器 $server : $_" -ForegroundColor Red
        $results += [PSCustomObject]@{
            ServerName  = $server
            KBNumber    = "N/A"
            Status      = "连接失败"
            Description = $_.Exception.Message
            CheckedTime = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
        }
    }
}

# 导出CSV报告
$results | Export-Csv -Path "C:\Scripts\PatchReport.csv" -NoTypeInformation -Encoding UTF8
Write-Host "报告已生成: C:\Scripts\PatchReport.csv" -ForegroundColor Green

使用CIM实例查询:更现代的方式

Get-HotFix底层其实是调用WMI的Win32_QuickFixEngineering类。现在微软推荐使用CIM(Common Information Model)接口,速度更快、更稳定。用Get-CimInstance替代Get-WmiObject,写法如下:

# 使用CIM查询已安装补丁
Get-CimInstance -ClassName Win32_QuickFixEngineering -ComputerName "Server01" | 
    Select-Object HotFixID, Description, InstalledOn |
    Sort-Object InstalledOn -Descending

CIM方式的优势在于:支持现代认证协议、对防火墙更友好、在PowerShell 7+中性能明显提升。如果你的环境已经升级到PowerShell 7,强烈建议用这套方式。

批量执行的前置条件配置

脚本能跑通的前提是远程管理已经配置好。你需要确保以下几点:第一,目标服务器开启了WinRM服务,可以用Enable-PSRemoting -Force一键开启;第二,防火墙放行了5985(HTTP)或5986(HTTPS)端口;第三,执行脚本的账号在目标服务器上有管理员权限;第四,所有服务器在同一个域环境或者配置了信任关系。如果是工作组环境,需要在每台机器上执行Set-Item WSMan:\localhost\Client\TrustedHosts -Value "*"来添加信任主机。

# 在目标服务器上开启远程管理
Enable-PSRemoting -Force

# 配置信任主机(工作组环境)
Set-Item WSMan:\localhost\Client\TrustedHosts -Value "*" -Force

# 确认WinRM服务状态
Get-Service WinRM

进阶:检查补丁安装后是否需要重启

很多补丁装完之后系统提示需要重启,但运维经常忽略这一步。PowerShell可以通过查询注册表来判断是否有待重启的挂起操作:

# 检查是否有挂起的重启
$rebootPending = $false

# 检查注册表项
$regKeys = @(
    "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\RebootPending",
    "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\RebootRequired",
    "HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\PendingFileRenameOperations"
)

foreach ($key in $regKeys) {
    if (Test-Path $key) {
        $rebootPending = $true
        break
    }
}

if ($rebootPending) {
    Write-Host "警告:该服务器有待处理的重启操作!" -ForegroundColor Yellow
}

把这个逻辑嵌入批量脚本,你就能同时知道"补丁装没装"和"需不需要重启"两个关键信息。

如何生成可视化报告

CSV报告虽然好用,但给领导汇报时不够直观。你可以用PowerShell生成HTML格式的报告,带颜色高亮,一目了然:

# 生成HTML报告
$html = $results | ConvertTo-Html -Property ServerName, KBNumber, Status, Description, CheckedTime -Title "Windows服务器补丁检查报告" -PreContent "

补丁检查报告 - $(Get-Date -Format 'yyyy-MM-dd')

" # 添加样式 $html = $html -replace "", "
" $html = $html -replace "
", "" $html = $html -replace "", "" $html = $html -replace "已安装", "已安装" $html = $html -replace "未安装", "未安装" $html | Out-File "C:\Scripts\PatchReport.html" -Encoding UTF8 Write-Host "HTML报告已生成"

定时自动执行:配合任务计划程序

手动跑脚本终归不是长久之计。你可以把脚本保存为.ps1文件,然后通过Windows任务计划程序设定每周自动执行。创建任务时选择"使用最高权限运行",触发器设为每周一凌晨,操作选择"启动程序"填写powershell.exe,参数写-ExecutionPolicy Bypass -File "C:\Scripts\CheckPatches.ps1"。这样每周一上班你就能收到最新的补丁状态报告。

常见问题与排错指南

实际使用中你一定会遇到几个典型问题。第一,Invoke-Command报错"访问被拒绝",多半是权限不够或者WinRM没配好,检查一下账户是否属于本地Administrators组。第二,脚本执行特别慢,这通常是因为没有限制并发数,可以用-ThrottleLimit参数控制同时连接的服务器数量,比如-ThrottleLimit 10表示同时处理10台。第三,某些旧版服务器(如Server 2008 R2)可能不支持CIM,需要回退到Get-WmiObject。第四,如果补丁列表特别长,建议把目标KB列表放在单独的配置文件里,方便维护。

# 控制并发数量
$results = Invoke-Command -ComputerName $servers -ScriptBlock { Get-HotFix } -ThrottleLimit 10 -ErrorAction SilentlyContinue

与WSUS和SCCM的配合使用

如果你的环境已经部署了WSUS(Windows Server Update Services)或者SCCM/MECM,PowerShell脚本可以作为补充手段。WSUS负责集中管理补丁分发,但它的报告有时候不够细或者有延迟。用PowerShell脚本做二次验证,相当于加了一道保险。你甚至可以写脚本直接调用WSUS的API来获取更详细的补丁合规数据,不过这属于更高阶的用法,需要单独学习WSUS的PowerShell模块。

安全注意事项

批量远程执行脚本涉及高权限操作,一定要注意安全。脚本文件要放在受控目录,不要随便放在共享文件夹里。执行账号遵循最小权限原则,不要用域管理员账号跑日常检查。脚本执行日志要保留,方便审计追溯。另外,如果服务器数量超过500台,建议分批执行,避免对网络和目标服务器造成过大压力。

总结

Windows服务器补丁批量检查这件事,说复杂也复杂,说简单其实核心就是三步:配好远程管理环境、写好PowerShell查询脚本、设定时自动执行并生成报告。Get-HotFix和CIM是两个核心查询接口,配合Invoke-Command实现批量,再加上HTML报告输出和任务计划定时运行,就构成了一套完整的自动化运维方案。这套方法不需要额外购买工具,纯靠系统自带能力就能搞定,适合各种规模的运维团队直接上手使用。

上一篇下一篇