Oamc

PowerShell 批量远程执行

本页目录

场景

几十台 Windows 服务器要统一查磁盘、重启服务、改注册表。

前置条件

  • 目标机开启 WinRM
  • 执行账号在目标机有管理员权限
  • 网络能到 5985(HTTP)或 5986(HTTPS)

配置

目标机开启 WinRM:

Enable-PSRemoting -Force
Set-Item WSMan:\localhost\Client\TrustedHosts -Value "10.0.0.*" -Force

本机批量执行:

$servers = Get-Content .\hosts.txt

Invoke-Command -ComputerName $servers -ThrottleLimit 16 -ScriptBlock {
    [pscustomobject]@{
        Host    = $env:COMPUTERNAME
        C_Free  = [math]::Round((Get-PSDrive C).Free / 1GB, 1)
        Uptime  = (Get-Date) - (Get-CimInstance Win32_OperatingSystem).LastBootUpTime
    }
} | Sort-Object C_Free | Format-Table -AutoSize

改服务:

Invoke-Command -ComputerName $servers -ScriptBlock {
    Restart-Service -Name Spooler -Force
}

PowerShell 7 的并行写法:

$servers | ForEach-Object -Parallel {
    Invoke-Command -ComputerName $_ -ScriptBlock { hostname }
} -ThrottleLimit 16

验证

Test-WSMan -ComputerName 10.0.0.21
Invoke-Command -ComputerName 10.0.0.21 -ScriptBlock { $env:COMPUTERNAME }

回滚

批量操作前先导出:

Invoke-Command -ComputerName $servers -ScriptBlock {
    Get-Service | Export-Csv "C:\temp\services_$env:COMPUTERNAME.csv" -NoTypeInformation
}

坑

  • Invoke-Command 里的脚本在目标机执行,本地变量要 -ArgumentList 传进去。
  • 返回对象经过序列化,方法和部分属性会丢。
  • WinRM 默认 HTTP,跨网段要配 HTTPS 或 TrustedHosts。
  • 凭据不能直接传字符串,用 $cred = Get-Credential 或 PSCredential 对象。
  • 大批量时不开 -ThrottleLimit,默认只并发 32,其实还好但目标机可能受不了。
  • 改注册表/服务的脚本先在一台上验证,别一次推全网。