0aa8fe6
这次没有正文改动。
这是 automation/PowerShell 批量远程执行.md 的改动记录。后台每次保存都会留一份快照,
这里显示的是快照之间的差异,不会混入其他文章的改动。
还没有后台修改记录。
下面是 Git 里的提交,可能包含其他文章的改动(因为一次提交会带上工作区所有变化)。
0aa8fe6
这次没有正文改动。
e4d2cd0
@@ -0,0 +1,81 @@ +--- +tags: [PowerShell, 批量, Windows] +order: 20 +--- + +# PowerShell 批量远程执行 + +## 场景 + +几十台 Windows 服务器要统一查磁盘、重启服务、改注册表。 + +## 前置条件 + +- 目标机开启 WinRM +- 执行账号在目标机有管理员权限 +- 网络能到 5985(HTTP)或 5986(HTTPS) + +## 配置 + +目标机开启 WinRM: + +```powershell +Enable-PSRemoting -Force +Set-Item WSMan:\localhost\Client\TrustedHosts -Value "10.0.0.*" -Force +``` + +本机批量执行: + +```powershell +$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 +``` + +改服务: + +```powershell +Invoke-Command -ComputerName $servers -ScriptBlock { + Restart-Service -Name Spooler -Force +} +``` + +PowerShell 7 的并行写法: + +```powershell +$servers | ForEach-Object -Parallel { + Invoke-Command -ComputerName $_ -ScriptBlock { hostname } +} -ThrottleLimit 16 +``` + +## 验证 + +```powershell +Test-WSMan -ComputerName 10.0.0.21 +Invoke-Command -ComputerName 10.0.0.21 -ScriptBlock { $env:COMPUTERNAME } +``` + +## 回滚 + +批量操作前先导出: + +```powershell +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,其实还好但目标机可能受不了。 +- 改注册表/服务的脚本先在一台上验证,别一次推全网。