如何实现PowerShell SSH脚本同时执行ip.txt中所有主机的命令
没问题!要让你的PowerShell脚本同时处理所有IP地址,我们可以利用PowerShell的并行处理能力,下面分两种常用场景给你修改后的脚本:
方法1:PowerShell 7+ 推荐使用
ForEach-Object -Parallel 如果你的环境已经升级到PowerShell 7或更高版本,这种方式最简洁高效,原生支持并行执行:
# 读取IP列表并过滤空行 $Computers = Get-Content -Path .\ip.txt | Where-Object { $_ -match '\S' } # 提前创建通用凭据,避免重复创建浪费资源 $User = "-" $Password = "-" $secpasswd = ConvertTo-SecureString $Password -AsPlainText -Force $Credentials = New-Object System.Management.Automation.PSCredential($User, $secpasswd) $Command = 'hostname' # 并行处理每台主机,-ThrottleLimit可以限制同时运行的数量(按需调整) $Computers | ForEach-Object -Parallel -ThrottleLimit 10 { $Computer = $_ Write-Host "正在处理主机: $Computer" # 清理当前会话的SSH信任主机列表 Get-SSHTrustedHost | Remove-SSHTrustedHost # 建立SSH会话 $SessionID = New-SSHSession -ComputerName $Computer -Credential $using:Credentials -AcceptKey:$true # 执行命令并提取输出 $output = Invoke-SSHCommand -Index $SessionID.SessionId -Command $using:Command | Select-Object -ExpandProperty Output # 用完会话记得关闭,避免资源泄漏 Remove-SSHSession -SessionId $SessionID.SessionId # 返回带主机标识的结果,方便后续写入文件 [PSCustomObject]@{ Computer = $Computer Output = $output -join "`n" } } | ForEach-Object { # 将结果写入文件,格式可以根据需求调整 Add-Content -Path result.txt -Value "$($_.Computer):`n$($_.Output)`n------------------------`n" }
为什么这么改?
ForEach-Object -Parallel会自动在后台启动多个并行线程,同时处理不同的IP- 用
$using:前缀传递外部变量到并行块中,保证每个线程能拿到正确的凭据和命令 - 增加了会话清理逻辑,避免残留未关闭的SSH连接
- 结果中绑定了主机IP,方便你在输出文件里区分不同主机的执行结果
方法2:兼容Windows PowerShell 5.1的后台作业方式
如果你的环境还在使用Windows PowerShell 5.1(老系统默认版本),可以用后台作业实现并行:
# 读取IP列表并过滤空行 $Computers = Get-Content -Path .\ip.txt | Where-Object { $_ -match '\S' } # 提前创建通用凭据 $User = "-" $Password = "-" $secpasswd = ConvertTo-SecureString $Password -AsPlainText -Force $Credentials = New-Object System.Management.Automation.PSCredential($User, $secpasswd) $Command = 'hostname' # 存储所有后台作业的实例 $jobs = @() # 为每个IP启动一个后台作业 foreach($Computer in $Computers){ Write-Host "启动主机 $Computer 的处理作业" $job = Start-Job -ScriptBlock { param($Computer, $Credentials, $Command) Write-Host "正在处理主机: $Computer" Get-SSHTrustedHost | Remove-SSHTrustedHost $SessionID = New-SSHSession -ComputerName $Computer -Credential $Credentials -AcceptKey:$true $output = Invoke-SSHCommand -Index $SessionID.SessionId -Command $Command | Select-Object -ExpandProperty Output Remove-SSHSession -SessionId $SessionID.SessionId # 返回带主机标识的结果 return [PSCustomObject]@{ Computer = $Computer Output = $output -join "`n" } } -ArgumentList $Computer, $Credentials, $Command $jobs += $job } # 等待所有后台作业完成 Write-Host "等待所有作业执行完成..." Wait-Job -Job $jobs | Out-Null # 收集所有作业结果并写入文件 foreach($job in $jobs){ $result = Receive-Job -Job $job Add-Content -Path result.txt -Value "$($result.Computer):`n$result.Output`n------------------------`n" # 清理已完成的作业,释放资源 Remove-Job -Job $job } Write-Host "所有处理完成,结果已写入result.txt"
注意事项
- 如果目标主机数量较多,建议调整
-ThrottleLimit(方法1)或控制同时启动的作业数(方法2),避免本地或目标主机资源过载 - 确保你已经安装了
Posh-SSH模块(没装的话可以用Install-Module Posh-SSH -Scope CurrentUser安装) - 两种方式都保留了信任主机清理逻辑,避免SSH连接时的证书验证问题
内容的提问来源于stack exchange,提问作者SySx
相关产品推荐
相关产品推荐

