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

PowerShell中Foreach -Parallel未并行运行的问题解决

问题描述

需要通过SMB协议检测多台计算机上\\$computer\users\foo\路径是否存在。由于大量计算机可能离线,SMB请求超时会耗费数秒,因此尝试用Foreach -Parallel实现并行执行,但实际运行速度和普通foreach无差异,未达到并行效果。

用于获取最近14天登录过的计算机并检测路径的代码如下:

workflow Find-FoosComputer
{
    $computers = Get-Adcomputer -filter * -properties name,LastLogon | where {$_.lastlogon -ne $NULL} | where {[datetime]($_.lastlogon) -le (get-date).AddDays(-14)}|select -expandproperty name
    foreach -parallel ($computer in $computers){
        ($computer, (Test-Path "\\$computer\users\foo\")) > "c:\temp\results.txt"
    }
}

请问如何让Foreach -Parallel真正实现并行,同时对所有计算机执行Test-Path检测?


解决方案

1. 核心问题分析

你的代码没实现真正并行的关键原因有两个:

  • Workflow的foreach -parallel默认并行度极低,且本身有额外性能开销;
  • 所有并行任务直接写入同一个文件,触发文件锁冲突,任务被迫串行等待。

推荐放弃Workflow,改用PowerShell原生并行特性,效率更高。


2. 实用并行方案

方案一:PowerShell 7+ 用ForEach-Object -Parallel

这是当前最简洁高效的并行方式:

# 获取最近14天登录过的计算机列表
$computers = Get-AdComputer -Filter * -Properties Name, LastLogon | 
    Where-Object { $_.LastLogon -ne $null -and [datetime]$_.LastLogon -ge (Get-Date).AddDays(-14) } | 
    Select-Object -ExpandProperty Name

# 并行检测,控制并发数避免网络拥堵
$results = $computers | ForEach-Object -Parallel {
    $computer = $_
    $timeout = 5 # 超时时间(秒)
    $pathExists = $false

    # 先快速检测机器是否在线,减少SMB等待时间
    if (Test-Connection -ComputerName $computer -Count 1 -Quiet -TimeoutSeconds 2) {
        # 用后台作业给Test-Path加超时
        $job = Start-Job -ScriptBlock { Test-Path "\\$using:computer\users\foo\" }
        if (Wait-Job $job -Timeout $timeout) {
            $pathExists = Receive-Job $job
        }
        Remove-Job $job -Force
    }

    # 返回结构化结果
    [PSCustomObject]@{
        ComputerName = $computer
        PathExists   = $pathExists
        Status       = switch ($pathExists) {
            $true { "在线且路径存在" }
            $false { "在线但路径不存在" }
            default { "超时/离线" }
        }
    }
} -ThrottleLimit 20 # 并发数根据环境调整,建议10-30

# 统一写入文件,避免冲突
$results | Export-Csv -Path "c:\temp\results.csv" -NoTypeInformation -Encoding UTF8

方案二:PowerShell 5.x 用Start-Job实现并行

如果仍在使用PowerShell 5.x,用后台作业实现:

$computers = Get-AdComputer -Filter * -Properties Name, LastLogon | 
    Where-Object { $_.LastLogon -ne $null -and [datetime]$_.LastLogon -ge (Get-Date).AddDays(-14) } | 
    Select-Object -ExpandProperty Name

# 批量创建后台作业
$jobs = $computers | ForEach-Object {
    Start-Job -ScriptBlock {
        $computer = $args[0]
        $pathExists = $false
        try {
            if (Test-Connection -ComputerName $computer -Count 1 -Quiet -TimeoutSeconds 2) {
                $pathExists = Test-Path "\\$computer\users\foo\"
            }
        } catch {}
        [PSCustomObject]@{
            ComputerName = $computer
            PathExists   = $pathExists
        }
    } -ArgumentList $_
}

# 等待所有作业完成并收集结果
$results = $jobs | Wait-Job | Receive-Job
# 清理后台作业
$jobs | Remove-Job -Force

# 写入结果文件
$results | Export-Csv -Path "c:\temp\results.csv" -NoTypeInformation -Encoding UTF8

3. 若坚持使用Workflow的修复方法

如果必须用Workflow,需修改文件写入逻辑并调整并行度:

workflow Find-FoosComputer
{
    $computers = Get-Adcomputer -filter * -properties name,LastLogon | 
        Where-Object { $_.lastlogon -ne $NULL -and [datetime]($_.lastlogon) -ge (get-date).AddDays(-14) } | 
        Select-Object -expandproperty name
    
    # 先收集所有并行结果,再统一写入
    $results = foreach -parallel -ThrottleLimit 20 ($computer in $computers){
        $timeout = 5
        $pathExists = $false
        # 用InlineScript+后台作业实现超时控制
        $job = InlineScript {
            $comp = $using:computer
            if (Test-Connection -ComputerName $comp -Count 1 -Quiet -TimeoutSeconds 2) {
                Test-Path "\\$comp\users\foo\"
            } else {
                $false
            }
        } -AsJob
        if (Wait-Job $job -Timeout $timeout) {
            $pathExists = Receive-Job $job
        }
        Remove-Job $job -Force
        @($computer, $pathExists)
    }
    
    # 统一写入文件,避免锁冲突
    $results | Out-File "c:\temp\results.txt" -Encoding UTF8
}

注意:Workflow性能不如原生并行方案,仅作为兼容选择。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 23:32:02