You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PowerShell Remoting会话超时配置与故障主机处理方案咨询

PowerShell 批量服务器WinRM连接管理脚本优化方案

原有脚本核心缺陷

  • 整批传入服务器列表创建PSSession时,连接失败的主机会被直接静默丢弃,无任何失败记录
  • Wait-Job设置的超时是针对整批任务的粗粒度控制,超时后未完成的单主机任务直接终止,无法追溯具体哪台主机超时
  • 无并行度控制,服务器规模达到数百台以上时容易触发本机端口耗尽、目标端WinRM连接限流问题
  • 无实时进度反馈,大规模执行时无法判断当前运行状态

优化后实现脚本

# 基础配置参数
$serverList = @('server1','server2','server3')
$connectionTimeout = 30 # 单台主机WinRM连接超时,单位秒
$operationTimeout = 30 # 单台主机远程命令执行超时,单位秒
$maxParallel = 50 # 最大并行执行数,建议根据网络环境调整为30~100区间
$cred = Get-Credential
$successList = [System.Collections.Concurrent.ConcurrentBag[psobject]]::new()
$failedList = [System.Collections.Concurrent.ConcurrentBag[psobject]]::new()

# 配置WinRM会话超时规则
$sessionOption = New-PSSessionOption -OpenTimeout $($connectionTimeout*1000) `
    -OperationTimeout $($operationTimeout*1000) `
    -CancelTimeout $($connectionTimeout*1000) `
    -NoMachineProfile

# 并行遍历处理所有主机
$serverList | ForEach-Object -Parallel {
    $targetServer = $_
    $success = $using:successList
    $failed = $using:failedList
    $opt = $using:sessionOption
    $credential = $using:cred

    Write-Host "[$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')] 开始处理主机: $targetServer"
    try {
        # 单台主机单独建立会话,捕获连接阶段异常
        $session = New-PSSession -ComputerName $targetServer -Credential $credential -SessionOption $opt -ErrorAction Stop
        try {
            # 执行远程命令,捕获执行阶段异常
            $result = Invoke-Command -Session $session -ScriptBlock {[System.Net.Dns]::GetHostName()} -ErrorAction Stop
            $success.Add(@{
                ServerName = $targetServer
                ReturnValue = $result
                Status = "Success"
            })
            Write-Host "[$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')] 主机 $targetServer 执行成功"
        }
        catch {
            $failed.Add(@{
                ServerName = $targetServer
                ErrorMsg = $_.Exception.Message
                Status = "CommandExecuteFailed"
            })
            Write-Host "[$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')] 主机 $targetServer 命令执行失败: $($_.Exception.Message)"
        }
        finally {
            # 主动释放会话资源,避免残留占用
            if ($session) { Remove-PSSession $session -ErrorAction SilentlyContinue }
        }
    }
    catch {
        $failed.Add(@{
            ServerName = $targetServer
            ErrorMsg = $_.Exception.Message
            Status = "ConnectionFailed"
        })
        Write-Host "[$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')] 主机 $targetServer 连接失败: $($_.Exception.Message)"
    }
} -ThrottleLimit $maxParallel

# 成功结果写入数据库
foreach ($item in $successList) {
    $serverName = $item.ServerName
    Invoke-Sqlcmd -ServerInstance "servername" -Query "insert into mytable select '$serverName'"
}

# 输出执行统计
Write-Host "`n执行完成,统计信息:"
Write-Host "总主机数: $($serverList.Count)"
Write-Host "执行成功: $($successList.Count)"
Write-Host "执行失败: $($failedList.Count)"
# 失败列表导出为CSV供排查使用,也可按需写入单独的异常日志表
$failedList | Export-Csv -Path ".\WinRM_Execute_Failed_$(Get-Date -Format 'yyyyMMddHHmmss').csv" -NoTypeInformation

关键配置说明

  • 并行度$maxParallel不建议设置超过100,过高并发会导致本机临时端口耗尽,反而降低整体执行效率,50左右的并行度处理数千台服务器总耗时基本可控制在10分钟以内
  • 会话选项单独配置了连接超时、执行超时、取消超时三个阈值,所有超时都是单主机粒度,不会出现整批任务超时导致的结果丢失问题
  • 采用线程安全的ConcurrentBag存储成功、失败结果,避免多线程并行下的集合写入冲突
  • 异常分类覆盖连接失败(主机离线、WinRM未启动、权限不足、网络不通)、命令执行失败两类场景,失败记录自带错误原因,无需事后做差集比对
  • 每台主机处理开始、成功、失败都有带时间戳的日志输出,可实时观测执行进度
  • 脚本默认使用PowerShell 7+内置的ForEach-Object -Parallel实现并行,如果需要兼容PowerShell 5.1,可将并行块替换为Start-ThreadJob实现,核心的异常捕获、超时配置逻辑无需修改

内容的提问来源于stack exchange,提问作者learner

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.31 08:33:20