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

将测试连接脚本改造为多线程版本求助

PowerShell多线程改造求助:批量主机检测脚本提速问题

我最近写了个PowerShell脚本,用来批量检测主机可用性——它能从文本文件读主机列表,把结果输出到屏幕和文件,还能在特定条件下自动发邮件。但是!一旦主机数量多起来,脚本跑起来慢得让人崩溃!我作为PowerShell新手,试着改成多线程版本,折腾了半天没搞定,有没有大佬能给我支支招呀?

以下是我目前的脚本片段:

# start looping here
Do{
    $available = @()
    $notavailable = @()
    $ComputerName = @()
    #Path to text file of hostnames we want to monitor
    $ComputerName = Get-Con...
}

适合新手的多线程改造方案

其实PowerShell里有几种简单的多线程实现方式,我给你推荐两种最实用的:

方案1:用ForEach-Object -Parallel(PowerShell 7+ 推荐)

这个语法最简洁,适合已经升级到PowerShell 7及以上版本的场景,自带并发控制:

# 1. 读取主机列表文件
$ComputerList = Get-Content -Path "C:\你的主机列表路径.txt"

# 2. 并行检测每个主机(设置并发数,按需调整)
$results = $ComputerList | ForEach-Object -Parallel {
    $hostname = $_
    # 用Test-Connection检测主机是否在线,也可以换成检测特定端口的Test-NetConnection
    if (Test-Connection -ComputerName $hostname -Count 1 -Quiet -ErrorAction SilentlyContinue) {
        [PSCustomObject]@{
            ComputerName = $hostname
            Status       = "Available"
            Timestamp    = Get-Date
        }
    } else {
        [PSCustomObject]@{
            ComputerName = $hostname
            Status       = "Not Available"
            Timestamp    = Get-Date
        }
    }
} -ThrottleLimit 50 # 并发数,根据你的机器性能和网络情况调整,别太高避免拥堵

# 3. 分离可用/不可用主机
$available = $results | Where-Object { $_.Status -eq "Available" }
$notavailable = $results | Where-Object { $_.Status -eq "Not Available" }

# 4. 输出结果到屏幕
Write-Host "`n可用主机列表:"
$available | Format-Table -AutoSize
Write-Host "`n不可用主机列表:"
$notavailable | Format-Table -AutoSize

# 5. 输出结果到文件
$available | Export-Csv -Path "AvailableHosts.csv" -NoTypeInformation
$notavailable | Export-Csv -Path "UnavailableHosts.csv" -NoTypeInformation

# 6. 特定条件下发邮件(比如有不可用主机时)
if ($notavailable.Count -gt 0) {
    $mailSettings = @{
        To          = "收件人邮箱@xxx.com"
        From        = "发件人邮箱@xxx.com"
        Subject     = "主机检测报告:$($notavailable.Count)台主机离线"
        Body        = "以下主机无法连接:`n$($notavailable.ComputerName -join "`n")"
        SmtpServer  = "你的SMTP服务器地址"
        # 如果需要认证可以加 -Credential (Get-Credential)
    }
    Send-MailMessage @mailSettings
}

方案2:用Start-Job(兼容PowerShell 5.1)

如果还在使用PowerShell 5.1,用Start-Job来实现多线程也很方便:

# 1. 读取主机列表
$ComputerList = Get-Content -Path "C:\你的主机列表路径.txt"
$jobs = @()

# 2. 给每个主机启动单独的检测任务
foreach ($hostname in $ComputerList) {
    $job = Start-Job -ScriptBlock {
        param($hostName)
        if (Test-Connection -ComputerName $hostName -Count 1 -Quiet -ErrorAction SilentlyContinue) {
            return [PSCustomObject]@{
                ComputerName = $hostName
                Status       = "Available"
                Timestamp    = Get-Date
            }
        } else {
            return [PSCustomObject]@{
                ComputerName = $hostName
                Status       = "Not Available"
                Timestamp    = Get-Date
            }
        }
    } -ArgumentList $hostname
    $jobs += $job
}

# 3. 等待所有任务完成并收集结果
$results = $jobs | Wait-Job | Receive-Job
# 清理已完成的作业,避免残留
$jobs | Remove-Job

# 后续的结果分离、输出、发邮件步骤和方案1完全一致,直接复用即可

新手小贴士

  • -ThrottleLimit(方案1)或者同时运行的Job数量(方案2)别设太高,不然可能导致网络拥堵或者本地机器卡顿,建议先从30-50开始测试
  • 如果需要检测特定服务(比如RDP、HTTP),把Test-Connection换成Test-NetConnection -Port 3389这类命令就行
  • 域环境下也可以用Invoke-Command来并行执行,效率也不错,但需要对应主机的访问权限

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 12:05:02