在 powershell 中并行运行任务

Posted

技术标签:

【中文标题】在 powershell 中并行运行任务【英文标题】:Running tasks parallel in powershell 【发布时间】:2017-09-26 21:16:10 【问题描述】:

我有一个这样的 PowerShell 脚本:

Foreach ($file in $files) 
    [Do something]
    [Do something]
    [Do something]

这样一个文件一个接一个地处理。我想同时处理 4 个文件。

我知道 foreach -parallel 循环,但它会并行执行 [do something] 任务。我基本上想并行运行整个 foreach 循环。

如何在 PowerShell 中实现这一点?

【问题讨论】:

【参考方案1】:

您可以查看Jobs 或runspaces。以下是 Jobs 的示例:

$block = 
    Param([string] $file)
    "[Do something]"

#Remove all jobs
Get-Job | Remove-Job
$MaxThreads = 4
#Start the jobs. Max 4 jobs running simultaneously.
foreach($file in $files)
    While ($(Get-Job -state running).count -ge $MaxThreads)
        Start-Sleep -Milliseconds 3
    
    Start-Job -Scriptblock $Block -ArgumentList $file

#Wait for all jobs to finish.
While ($(Get-Job -State Running).count -gt 0)
    start-sleep 1

#Get information from each job.
foreach($job in Get-Job)
    $info= Receive-Job -Id ($job.Id)

#Remove all jobs created.
Get-Job | Remove-Job

在上面的代码中,每个$file 都彼此并行运行(最多同时运行 4 个)。

编辑:作为对 cme​​ts 的回应,here 是一些关于脚本块的文档。为什么必须包含参数的简短原因是因为与 PowerShell 函数不同,脚本块不能在大括号 之外指定参数。

【讨论】:

做得很好,但我建议使用Wait-Job cmdlet 而不是您包含的所有花哨的逻辑来获取正在运行的作业并等待它们完成。 Link to alternative walk-through of runspaces that I personally learned it from and like. 哦,你应该解释一下为什么必须将$file 参数传递到你的脚本块中。 我会为以后的脚本研究这个。我不知道 Wait-Job 存在。 这种使用作业的方法加载和过滤文件的速度要慢得多。我认为它会更快,因为可以同时加载和过滤 4 个文件。但实际上一个接一个地加载和过滤文件要快得多。你怎么解释这个?有没有办法让它更快? 您愿意添加一个使用运行空间的示例吗?我正在阅读并尝试将您的工作示例转换为使用运行空间,但无法弄清楚。【参考方案2】:

Powershell 7 引入foreach-object -parallel

https://devblogs.microsoft.com/powershell/powershell-foreach-object-parallel-feature/

然后你的脚本会说

$files | ForEach-Object -parallel 
    [Do something]
    [Do something]
    [Do something]

【讨论】:

【参考方案3】:

根据Get-Help about_Foreach-ParallelForEach -Parallel... 将为每个项目并行处理整个脚本块,但脚本块中的命令将按顺序处理(尽管如果用Parallel ... 括起来,它们可能会被并行化)。但是,您的脚本必须是 PowerShell 工作流程才能被接受; ParallelSequence 关键字仅在工作流中有效。

【讨论】:

来自 msdn.microsoft.com/en-us/powershell/reference/5.1/psworkflow/… :描述 Windows PowerShell 工作流中的 ForEach -Parallel 语言结构。如果您使用工作流,则 -Parallel 参数不存在。我没有感觉到 OP 正在处理工作流。 @tommymaynard - 是的,Parallel 开关和构造仅适用于工作流,我确实注意到了这一点。提问者在他的问题中确实提到了Foreach -parallel 构造,但似乎误解了效果,所以我假设工作流是一种可能性,并在此基础上回答。如果他不是,那么好奇一号给出的工作解决方案可能就是要走的路。 你说得对,你确实提到了工作流程。很抱歉!

以上是关于在 powershell 中并行运行任务的主要内容,如果未能解决你的问题,请参考以下文章

PowerShell 添加任务以使用参数运行 PowerShell 脚本

TFS 任务在远程计算机上运行 Power shell 错误:System.Management.Automation.RuntimeException:无法安装“VisualStudioRemote

运行 Azure Powershell 内联脚本

power shell 更新后的版本号

并行执行任务

如何使用Windows Power Shell