bestsource

Powershell 명령어를 병렬로 실행할 수 있습니까?

bestsource 2023. 4. 9. 21:47
반응형

Powershell 명령어를 병렬로 실행할 수 있습니까?

다수의 이미지를 일괄 처리하는 powershell 스크립트를 가지고 있으며 병렬 처리를 하고 싶습니다.Powershell에는 시작 작업, 대기 작업 등의 백그라운드 처리 옵션이 몇 가지 있는 것 같습니다만, 병렬 작업을 실시하기 위한 유일한 리소스는 스크립트 텍스트를 작성하고 실행하는 것이었습니다(PowerShell 멀티스레딩).

이상적으로는 .net 4의 평행 포어치 같은 것을 원합니다.

뭔가 좀 아닌 것 같죠?

foreach-parallel -threads 4 ($file in (Get-ChildItem $dir))
{
   .. Do Work
}

그냥 c#으로 내려가는 게 나을 것 같은데...

백그라운드 작업을 사용하여 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

스티브 타운센드의 대답은 이론적으로는 맞지만 실제론 @likwid가 지적한 것처럼 정확하지 않다.개정된 코드에는 직무 컨텍스트 장벽이 고려되어 있습니다.기본적으로 그 장벽을 넘는 것은 없습니다.오토매틱$_따라서 변수는 루프에서 사용할 수 있지만 작업에 의해 작성된 별도의 컨텍스트 내에 있기 때문에 스크립트블록 내에서 직접 사용할 수 없습니다.

하려면 , 「」를합니다.-ArgumentListStart-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 *

(일반적으로 PowerShell 문서를 참고 자료로 제공하고 싶지만 안타깝게도 검색 결과가 없었습니다.콘텍스트 분리가 문서화되어 있는 장소를 알고 있는 경우는, 여기에 코멘트를 달아 주세요.

오늘날에는 이에 대한 해답이 매우 많습니다.

  1. 작업(또는 PS 6/7의 스레드 작업 또는 PS 5의 모듈)
  2. 개시 프로세스
  3. 워크플로우(PS 5 한정)
  4. powershell api와 다른 runspace를 사용합니다.
  5. 여러 컴퓨터가 있는 invoke 명령어(모두 localhost일 수 있음)(admin이어야 함)
  6. ISE의 여러 세션(런스페이스) 탭 또는 리모트 powershell ISE 탭
  7. 에는 Powershell 7이 되어 있습니다.foreach-object -parallel#4의

powershell 5.1에서 start-threadjob을 사용한다.기대했던 대로 작동했으면 좋겠지만, 그렇지 않습니다.

# test-netconnection has a miserably long timeout
echo yahoo.com facebook.com | 
  start-threadjob { test-netconnection $input } | receive-job -wait -auto

WARNING: Name resolution of yahoo.com microsoft.com facebook.com failed

이런 식으로 작동합니다.powershell 7에 필적하는, 그다지 훌륭하지 않고 포어치 오브젝트도 아니지만, 그럴 것이다.

echo yahoo.com facebook.com | 
  % { $_ | start-threadjob { test-netconnection $input } } | 
  receive-job -wait -auto | ft -a

ComputerName RemotePort RemoteAddress PingSucceeded PingReplyDetails (RTT) TcpTestS
                                                                           ucceeded
------------ ---------- ------------- ------------- ---------------------- --------
facebook.com 0          31.13.71.36   True          17 ms                  False
yahoo.com    0          98.137.11.163 True          97 ms                  False

다음은 말 그대로 전치 병렬이 포함된 워크플로우입니다.

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

work

3 done
1 done
2 done

또는 병렬 블록이 있는 워크플로우:

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

다음은 runspaces를 사용하는 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

Powershell 7에서는 각 객체에 대해 병렬을 사용할 수 있습니다.

$Message = "Output:"
Get-ChildItem $dir | ForEach-Object -Parallel {
    "$using:Message $_"
} -ThrottleLimit 4

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

invoke-clocks/clocks/clocks를 동시에 실행할 수 있는 invoke-clocks를 만들었습니다.이는 작은 작업(기동 작업의 시작 시간과 비교하여 런스페이스 생성에 대한 오버헤드가 상당히 크기 때문에 100대의 머신에 대해 스캔 또는 WMI 쿼리를 실행)에 적합합니다.이렇게 쓸 수 있어요.

스크립트 블록 포함,

$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

cmdlet/기능만

$servers = Get-Content servers.txt 

$rtn = Invoke-Async -Set $servers -SetParam computername -Params @{count=1} -Cmdlet Test-Connection -ThreadCount 50

백그라운드 작업은 설정 비용이 많이 들고 재사용할 수 없습니다.PowerShell MVP Oisin Grehan은 PowerShell 멀티스레딩의 좋은 입니다.

(2010년 10월 25일 사이트가 다운되었지만 웹 아카이브를 통해 액세스할 수 있습니다).

데이터 로딩 루틴에서 사용하기 위해 Oisin 스크립트를 사용했습니다.

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

이전 답변을 완료하려면 다음을 사용할 수도 있습니다.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

최신 크로스 플랫폼 powershell을 사용하는 경우(이것이 필요) https://github.com/powershell/powershell#get-powershell, 를 1 개 추가할 수 있습니다.&병렬 스크립트를 실행합니다.;순차적으로 실행)

제 경우 2개의 npm 스크립트를 동시에 실행해야 했습니다.npm run hotReload & npm run dev


npm을 설정하여powershell(디폴트에서는,cmd를 참조해 주세요).

프로젝트 루트 폴더에서 실행:npm config set script-shell pwsh --userconfig ./.npmrc그런 다음 단일 npm 스크립트명령어를 사용합니다.npm run start

"start":"npm run hotReload & npm run dev"

이것은 충분히 해결되었습니다.참고용으로 Powershell-Jobs를 기반으로 만든 이 메서드를 게시하고 싶습니다.

작업은 스크립트 블록 목록으로 전달됩니다.파라미터화할 수 있습니다.작업의 출력은 색상으로 구분되어 작업 인덱스로 프리픽스가 붙습니다(빌드에서 사용되는 것과 마찬가지로 vs-build 프로세스에서도 마찬가지).한 번에 여러 서버를 시작하거나 빌드 단계를 병렬로 실행할 때 사용할 수 있습니다.

function Start-Parallel {
    param(
        [ScriptBlock[]]
        [Parameter(Position = 0)]
        $ScriptBlock,

        [Object[]]
        [Alias("arguments")]
        $parameters
    )

    $jobs = $ScriptBlock | ForEach-Object { Start-Job -ScriptBlock $_ -ArgumentList $parameters }
    $colors = "Blue", "Red", "Cyan", "Green", "Magenta"
    $colorCount = $colors.Length

    try {
        while (($jobs | Where-Object { $_.State -ieq "running" } | Measure-Object).Count -gt 0) {
            $jobs | ForEach-Object { $i = 1 } {
                $fgColor = $colors[($i - 1) % $colorCount]
                $out = $_ | Receive-Job
                $out = $out -split [System.Environment]::NewLine
                $out | ForEach-Object {
                    Write-Host "$i> "-NoNewline -ForegroundColor $fgColor
                    Write-Host $_
                }
                
                $i++
            }
        }
    } finally {
        Write-Host "Stopping Parallel Jobs ..." -NoNewline
        $jobs | Stop-Job
        $jobs | Remove-Job -Force
        Write-Host " done."
    }
}

출력 예:

샘플 출력

PowerShell 7.0 Preview 3에는 새로운 솔루션이 내장되어 있습니다.각 오브젝트의 PowerShell 병렬 기능

다음과 같은 작업을 수행할 수 있습니다.

Get-ChildItem $dir | ForEach-Object -Parallel {

.. Do Work
 $_ # this will be your file

}-ThrottleLimit 4

언급URL : https://stackoverflow.com/questions/4016451/can-powershell-run-commands-in-parallel

반응형