PowerShell에서 병렬로 명령 실행

Marion Paul Kenneth Mendoza 2023년6월21일
  1. Windows PowerShell 멀티스레딩
  2. PSJob을 사용한 스크립트 병렬 실행
  3. 우리의 작업을 추적
  4. 작업 출력 검색
  5. 예약된 작업 만들기
PowerShell에서 병렬로 명령 실행

기본 PowerShell 세션은 단일 스레드입니다. 하나의 명령을 실행하고 다음 명령으로 이동합니다.

이 방법은 모든 것을 반복 가능하게 유지하고 많은 리소스를 사용하지 않기 때문에 탁월합니다. 이 경우 멀티스레딩에 대해 생각하기 시작할 때입니다.

이 기사에서는 다양한 PowerShell 멀티스레딩 기술을 이해하고 사용하여 여러 데이터 스트림을 동시에 처리하지만 동일한 콘솔을 통해 관리하는 방법을 알려줍니다.

Windows PowerShell 멀티스레딩

다중 스레딩은 한 번에 둘 이상의 명령을 실행하는 방법입니다. PowerShell은 일반적으로 단일 스레드를 사용합니다. 스크립트를 병렬화하기 위해 둘 이상을 사용하는 많은 방법이 있습니다.

멀티스레딩의 주요 목적은 코드의 실행 시간을 줄이는 것입니다. 이 시간 감소는 더 높은 처리 능력 요구 사항과 절충됩니다.

또한 멀티스레딩 시 많은 작업이 동시에 수행되므로 더 많은 시스템 리소스가 필요합니다.

완벽한 스케일링은 볼 수 없습니다. 스크립트에서 항목을 회전 및 해제하는 데 시간이 걸립니다.

PowerShell은 단일 스레드를 사용하여 코드를 실행해야 하며 완료되었습니다. 콘솔을 실행하는 데 사용되는 원래 스레드를 사용하여 여러 스레드가 있는 다른 스레드를 관리합니다.

해당 원래 스레드는 특정 지점에서 최대가 되어 다른 모든 스레드를 일직선으로 유지합니다.

PSJob을 사용한 스크립트 병렬 실행

스크립트를 다중 스레드하는 가장 편리한 방법 중 하나는 PSJobs를 사용하는 것입니다. PSJobs에는 Microsoft.PowerShell.Core 모듈에 내장된 cmdlet이 있습니다.

Microsoft.PowerShell.Core 모듈은 버전 3부터 모든 버전의 PowerShell에 포함되었습니다. 이 모듈의 명령을 사용하면 포그라운드에서 다른 코드를 계속 실행하면서 백그라운드에서 코드를 실행할 수 있습니다.

Get-Command *-Job

우리의 작업을 추적

아래에서 작업이 있을 수 있는 가장 일반적인 상태 목록을 찾을 수 있습니다.

  1. 완료됨 – 작업이 완료되었으며 출력 데이터를 검색하거나 작업을 제거할 수 있습니다.
  2. 실행 중 – 작업이 실행 중이며 작업을 강제로 중지하지 않으면 제거할 수 없습니다. 출력을 검색할 수 없습니다.
  3. Blocked – 작업이 계속 실행 중이지만 실행을 계속하기 전에 사용자에게 추가 정보를 묻는 메시지가 표시됩니다.
  4. 실패 – 작업이 실행되는 동안 종료 오류가 발생했습니다.

Get-Job 명령을 사용하여 시작된 작업 상태와 작업의 모든 속성을 가져옵니다. 상태를 볼 수 있는 작업의 출력은 실행 중입니다.

아래 예제는 Start-Job 명령을 사용하여 약속 내에서 Start-Sleep 5 코드를 실행합니다. 해당 작업의 상태는 Get-Job 명령을 사용하여 반환됩니다.

예제 코드:

Start-Job -Scriptblock {Start-Sleep 5}
Get-Job

출력:

Id     Name            PSJobTypeName   State         HasMoreData     Location             Command
--     ----            -------------   -----         -----------     --------             -------
1      Job1            BackgroundJob   Running       True            localhost            Start-Sleep 5

작업 출력 검색

때로는 작업 내부의 코드가 출력을 반환합니다. Receive-Job 명령을 사용하여 해당 코드를 검색할 수 있습니다.

PSJob을 입력으로 수락한 다음 작업 작업을 콘솔에 기록합니다. 실행 중 작업에서 발생한 모든 항목이 저장되었습니다.

작업을 검색하면 저장된 모든 내용이 표시됩니다.

이에 대한 예는 아래 스크립트를 실행하는 것입니다. 이 스크립트는 Hello World 문자열을 출력에 쓰는 작업을 생성하고 시작합니다.

그런 다음 작업에서 출력을 가져와 콘솔에 표시합니다.

예제 코드:

$Job = Start-Job -ScriptBlock {Write-Output 'Hello World'}
Receive-Job $Job

출력:

Hello World

예약된 작업 만들기

PSJobs와 상호 작용하는 또 다른 방법은 예약된 작업을 통하는 것입니다. 작업 스케줄러로 구성할 수 있는 Windows 예약 작업과 유사합니다.

예약된 약속은 예약된 작업에서 복잡한 PowerShell 스크립트 블록을 쉽게 예약하는 방법을 만듭니다. 그런 다음 트리거를 기반으로 백그라운드에서 PSJob을 실행할 수 있습니다.

작업 트리거

작업 트리거는 사용자가 로그온할 때, 시스템이 부팅될 때 및 기타 많은 시간이 될 수 있습니다. 트리거가 일정 간격으로 반복되도록 할 수도 있습니다.

이러한 트리거는 예약된 작업을 실행할 트리거를 지정하는 New-JobTrigger 명령으로 정의됩니다.

PSJob 트리거 외에도 일반 PSJob과 함께 사용되는 것과 같은 스크립트 블록이 있습니다. 트리거와 스크립트 블록이 모두 있으면 다음 섹션과 같이 Register-ScheduledJob 명령을 사용하여 작업을 생성합니다.

이 명령은 실행될 스크립트 블록과 New-JobTrigger 명령으로 생성된 트리거와 같은 예약된 작업의 속성을 지정합니다.

누군가가 컴퓨터에 로그인할 때마다 실행할 PowerShell 코드가 필요할 수 있습니다. 이를 위해 예약된 작업을 만들 수 있습니다.

먼저 New-JobTrigger를 사용하여 트리거를 정의하고 아래와 같이 예약된 작업을 지정합니다. 아래의 이 예약된 작업은 누군가가 시스템에 로그인할 때마다 로그 파일에 한 줄을 기록합니다.

예제 코드:

$Trigger = New-JobTrigger -AtLogon
$Script = {"User $env:USERNAME logged at $(Get-Date -Format 'y-M-d H:mm:ss')" | Out-File -FilePath C:\Temp\User_Login.log -Append}

Register-ScheduledJob -Name Login_Log -ScriptBlock $Script -Trigger $Trigger

출력:

Id         Name            JobTriggers     Command                                  Enabled   
--         ----            -----------     -------                                  -------   
1          Login_Log       1               "User $env:USERNAME logged at $(Ge... True

위의 명령을 실행하면 ID, 스크립트 블록 및 기타 속성을 표시하는 새 작업을 수행할 때와 유사한 결과를 얻을 수 있습니다.

AsJob 매개변수 사용

작업의 또 다른 용도는 많은 PowerShell 명령에 내장된 -AsJob 매개변수입니다. 다양한 명령이 있으므로 Get-Command를 사용하여 모든 명령을 찾을 수 있습니다.

Get-Command -ParameterName AsJob

가장 널리 사용되는 cmdlet 중 하나는 Invoke-Command입니다. 일반적으로 이 명령을 실행하면 명령 실행이 즉시 시작됩니다.

그러나 일부 명령은 즉시 반환되어 하던 작업을 계속할 수 있지만 일부는 cmdlet이 완료될 때까지 기다립니다.

대부분의 경우 로컬 시스템에서 AsJob 매개 변수를 사용할 수 있지만 Invoke-Command cmdlet에는 로컬 시스템에서 실행할 기본 옵션이 없습니다. 그러나 ComputerName 매개 변수 값으로 Localhost를 사용하여 해결 방법이 있습니다.

예:

Invoke-Command -ScriptBlock {Start-Sleep 5} -ComputerName localhost

아래 스크립트는 Invoke-Command cmdlet을 사용하여 5초 동안 절전 모드로 전환한 다음 AsJob 매개 변수를 사용하여 동일한 명령을 반복하여 실행 시간의 차이를 보여줍니다.

예제 코드:

Measure-Command {Invoke-Command -ScriptBlock {Start-Sleep 5}}
Measure-Command {Invoke-Command -ScriptBlock {Start-Sleep 5} -AsJob -ComputerName localhost}

출력:

Days              : 0
Hours             : 0
Minutes           : 0
Seconds           : 5
Milliseconds      : 20
Ticks             : 50206571
TotalDays         : 5.81094571759259E-05
TotalHours        : 0.00139462697222222
TotalMinutes      : 0.0836776183333333
TotalSeconds      : 5.0206571
TotalMilliseconds : 5020.6571

Days              : 0
Hours             : 0
Minutes           : 0
Seconds           : 0
Milliseconds      : 36
Ticks             : 365754
TotalDays         : 4.23326388888889E-07
TotalHours        : 1.01598333333333E-05
TotalMinutes      : 0.00060959
TotalSeconds      : 0.0365754
TotalMilliseconds : 36.5754
Marion Paul Kenneth Mendoza avatar Marion Paul Kenneth Mendoza avatar

Marion specializes in anything Microsoft-related and always tries to work and apply code in an IT infrastructure.

LinkedIn