Powershell可以并行运行命令吗?

Ala*_*son 115 parallel-processing powershell multithreading

我有一个powershell脚本对一堆图像进行一些批处理,我想做一些并行处理.Powershell似乎有一些后台处理选项,如启动作业,等待作业等,但我找到的并行工作的唯一好资源是编写脚本文本并运行它们(PowerShell多线程)

理想情况下,我喜欢类似于.net 4中的并行foreach的东西.

有点像:

foreach-parallel -threads 4 ($file in (Get-ChildItem $dir))
{
   .. Do Work
}
Run Code Online (Sandbox Code Playgroud)

也许我会更好的只是下降到c#...

Mic*_*ens 92

史蒂夫汤森的回答在理论上是正确的,但在实践中却没有,正如@likwid指出的那样.我修改后的代码考虑了工作环境障碍 -默认情况下没有任何障碍超越这个障碍!因此,自动$_变量可以在循环中使用,但不能直接在脚本块中使用,因为它位于作业创建的单独上下文中.

要将变量从父上下文传递到子上下文,请使用-ArgumentList参数on Start-Job发送它并param在脚本块内部使用它来接收它.

cls
# Send in two root directory names, one that exists and one that does not.
# Should then get a "True" and a "False" result out the end.
"temp", "foo" | %{

  $ScriptBlock = {
    # accept the loop variable across the job-context barrier
    param($name) 
    # Show the loop variable has made it through!
    Write-Host "[processing '$name' inside the job]"
    # Execute a command
    Test-Path "\$name"
    # Just wait for a bit...
    Start-Sleep 5
  }

  # Show the loop variable here is correct
  Write-Host "processing $_..."

  # pass the loop variable across the job-context barrier
  Start-Job $ScriptBlock -ArgumentList $_
}

# Wait for all to complete
While (Get-Job -State "Running") { Start-Sleep 2 }

# Display output from all jobs
Get-Job | Receive-Job

# Cleanup
Remove-Job *
Run Code Online (Sandbox Code Playgroud)

(我通常喜欢提供PowerShell文档的参考作为支持证据,但是,唉,我的搜索没有结果.如果您碰巧知道上下文分离的记录,请在此发表评论以告诉我!)


Ste*_*end 88

您可以使用后台作业在Powershell 2中执行并行作业.查看Start-Job和其他作业cmdlet.

# Loop through the server list
Get-Content "ServerList.txt" | %{

  # Define what each job does
  $ScriptBlock = {
    param($pipelinePassIn) 
    Test-Path "\\$pipelinePassIn\c`$\Something"
    Start-Sleep 60
  }

  # Execute the jobs in parallel
  Start-Job $ScriptBlock -ArgumentList $_
}

Get-Job

# Wait for it all to complete
While (Get-Job -State "Running")
{
  Start-Sleep 10
}

# Getting the information back from the jobs
Get-Job | Receive-Job
Run Code Online (Sandbox Code Playgroud)

  • 所以我多次尝试过这个建议,但似乎我的变量没有得到正确的扩展.要使用相同的示例,当此行执行时:`Test-Path"\\ $ _\c $\Something"`我希望它将`$ _`扩展到当前项目中.但事实并非如此.相反,它返回一个空值.这似乎只发生在脚本块中.如果我在第一个评论后立即写出该值,它似乎正常工作. (3认同)

izh*_*rsa 14

在 Powershell 7 中,您可以使用ForEach-Object -Parallel

$Message = "Output:"
Get-ChildItem $dir | ForEach-Object -Parallel {
    "$using:Message $_"
} -ThrottleLimit 4
Run Code Online (Sandbox Code Playgroud)


jri*_*523 8

http://gallery.technet.microsoft.com/scriptcenter/Invoke-Async-Allows-you-to-83b0c9f0

我创建了一个invoke-async,允许您同时运行多个脚本块/ cmdlet /函数.这对于小型作业(子网扫描或针对100台计算机的wmi查询)非常有用,因为创建运行空间的开销与启动作业的启动时间非常相似.它可以像这样使用.

使用scriptblock,

$sb = [scriptblock] {param($system) gwmi win32_operatingsystem -ComputerName $system | select csname,caption} 

$servers = Get-Content servers.txt 

$rtn = Invoke-Async -Set $server -SetParam system  -ScriptBlock $sb
Run Code Online (Sandbox Code Playgroud)

只是cmdlet/function

$servers = Get-Content servers.txt 

$rtn = Invoke-Async -Set $servers -SetParam computername -Params @{count=1} -Cmdlet Test-Connection -ThreadCount 50
Run Code Online (Sandbox Code Playgroud)


Cha*_*ler 7

后台作业设置昂贵且不可重复使用.PowerShell MVP Oisin Grehan有一个很好的PowerShell多线程示例http://www.nivot.org/2009/01/22/CTP3TheRunspaceFactoryAndPowerShellAccelerators.aspx

(10/25/2010网站已关闭):

我在这里使用了改编的Oisin脚本用于数据加载例程:

http://rsdd.codeplex.com/SourceControl/changeset/view/a6cd657ea2be#Invoke-RSDDThreaded.ps1


Jer*_*yal 7

如果您使用的是最新的跨平台 powershell(顺便说一句,您应该使用它)https://github.com/powershell/powershell#get-powershell,您可以添加单个&来运行并行脚本。(用于;顺序运行)

就我而言,我需要并行运行 2 个 npm 脚本:npm run hotReload & npm run dev


您还可以设置 npm 以用于powershell其脚本(默认情况下它cmd在 Windows 上使用)。

从项目根文件夹运行:npm config set script-shell pwsh --userconfig ./.npmrc 然后使用单个 npm 脚本命令:npm run start

"start":"npm run hotReload & npm run dev"
Run Code Online (Sandbox Code Playgroud)


Tho*_*mas 6

要完成之前的答案,您还可以使用Wait-Job等待所有作业完成:

For ($i=1; $i -le 3; $i++) {
    $ScriptBlock = {
        Param (
            [string] [Parameter(Mandatory=$true)] $increment
        )

        Write-Host $increment
    }

    Start-Job $ScriptBlock -ArgumentList $i
}

Get-Job | Wait-Job | Receive-Job
Run Code Online (Sandbox Code Playgroud)


js2*_*010 5

这些天有这么多答案:

  1. 作业(或PS 6/7或模块中的threadjob)
  2. 开始过程
  3. 工作流程
  4. Powershell API与另一个运行空间
  5. 具有多台计算机的invoke-command都可以是localhost(必须是admin)
  6. ISE中的多个会话(运行空间)选项卡,或远程Powershell ISE选项卡
  7. Powershell 7可以foreach-object -parallel替代#4

这是从字面上来说是foreach -parallel的工作流程:

workflow work {
  foreach -parallel ($i in 1..3) { 
    sleep 5 
    "$i done" 
  }
}

work

3 done
1 done
2 done
Run Code Online (Sandbox Code Playgroud)

或带有并行块的工作流程:

function sleepfor($time) { sleep $time; "sleepfor $time done"}

workflow work {
  parallel {
    sleepfor 3
    sleepfor 2
    sleepfor 1
  }
  'hi'
}

work 

sleepfor 1 done
sleepfor 2 done
sleepfor 3 done
hi
Run Code Online (Sandbox Code Playgroud)

这是带有运行空间示例的api:

$a =  [PowerShell]::Create().AddScript{sleep 5;'a done'}
$b =  [PowerShell]::Create().AddScript{sleep 5;'b done'}
$c =  [PowerShell]::Create().AddScript{sleep 5;'c done'}
$r1,$r2,$r3 = ($a,$b,$c).begininvoke() # run in background
$a.EndInvoke($r1); $b.EndInvoke($r2); $c.EndInvoke($r3) # wait
($a,$b,$c).streams.error # check for errors
($a,$b,$c).dispose() # clean

a done
b done
c done
Run Code Online (Sandbox Code Playgroud)

  • 可能值得注意的是,自 PowerShell 6 起(即自 PowerShell 切换到 .NET Core 起),工作流不再受支持。它们构建在 Windows Workflow Foundation 之上,而 .NET Core 中不提供该功能。虽然有“仅限 PS 5”的备注,但很容易被忽视。 (3认同)
  • Start-Process 通常会创建一个新窗口。使用 -NoNewWindow,进程可以直接访问当前控制台。这与 jobs 和 ForEach-Object -Parallel 不同,它们以某种方式处理输出。 (2认同)