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,其实还好但目标机可能受不了。 - 改注册表/服务的脚本先在一台上验证,别一次推全网。