PowerShell でコマンドを並列実行する
デフォルトの PowerShell セッションはシングルスレッドです。 1つのコマンドを実行し、次のコマンドに移動します。
この方法は、すべてを反復可能に保ち、多くのリソースを使用しないため、優れています。 その場合は、マルチスレッドについて考え始めるときです。
この記事では、さまざまな PowerShell マルチスレッド手法を理解して使用し、複数のデータ ストリームを同時に処理しながら同じコンソールで管理する方法を説明します。
Windows PowerShell マルチスレッド
マルチスレッドは、一度に複数のコマンドを実行する方法です。 PowerShell は通常、単一のスレッドを使用します。 スクリプトを並列化するために複数の方法を使用する方法はたくさんあります。
マルチスレッドの主な目的は、コードの実行時間を短縮することです。 この時間の短縮は、より高い処理能力要件とのトレードオフです。
さらに、マルチスレッドでは多くのアクションが一度に実行されるため、より多くのシステム リソースが必要になります。
完全なスケーリングは見られないことに注意してください。 スクリプト内のアイテムのスピンアップとティアダウンには、しばらく時間がかかります。
PowerShell は、単一のスレッドを使用してコードを実行する必要があり、これで完了です。 コンソールの実行に使用された元のスレッドを使用して、複数のスレッドを持つ他のスレッドを管理します。
その元のスレッドは、他のすべてのスレッドを維持しながら、特定の時点で最大になります。
PSJob によるスクリプトの並列実行
スクリプトをマルチスレッド化する最も便利な方法の 1つは、PSJobs
を使用することです。 PSJobs
には、Microsoft.PowerShell.Core
モジュールに組み込まれたコマンドレットがあります。
Microsoft.PowerShell.Core
モジュールは、バージョン 3 以降の PowerShell のすべてのバージョンに含まれています。このモジュールのコマンドを使用すると、フォアグラウンドで別のコードを実行し続けながら、バックグラウンドでコードを実行できます。
Get-Command *-Job
私たちの仕事を追跡する
以下に、ジョブが取り得る最も一般的な状態のリストを示します。
Completed
– ジョブが終了しました。出力データを取得するか、ジョブを削除できます。実行中
– ジョブは実行中であり、ジョブを強制的に停止しないと削除できません。 出力を取得できません。Blocked
– ジョブはまだ実行中ですが、ユーザーは実行を続行する前に追加情報の入力を求められています。Failed
– ジョブの実行中にスローされた終了エラーが発生しました。
Get-Job
コマンドを使用して、開始されたジョブのステータスとジョブのすべての属性を取得します。 状態を確認できるジョブの出力は Running
です。
以下の例では、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
を操作するもう 1つの方法は、スケジュールされたジョブを使用することです。 これは、タスク スケジューラで構成できる 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
パラメータを使用する
ジョブのもう 1つの用途は、多くの PowerShell コマンドに組み込まれている -AsJob
パラメーターです。 さまざまなコマンドがあるため、Get-Command
を使用してそれらすべてを見つけることができます。
Get-Command -ParameterName AsJob
最も一般的なコマンドレットの 1つは、Invoke-Command
です。 通常、このコマンドを実行すると、すぐにコマンドの実行が開始されます。
ただし、一部のコマンドはすぐに返され、実行していたことを続行できるようになりますが、コマンドレットが終了するまで待機するコマンドもあります。
ほとんどの場合、ローカル マシンで AsJob
パラメーターを使用できますが、Invoke-Command
コマンドレットには、ローカル マシンで実行するためのネイティブ オプションがありません。 ただし、ComputerName
パラメータ値として Localhost
を使用することによる回避策があります。
例:
Invoke-Command -ScriptBlock {Start-Sleep 5} -ComputerName localhost
以下のスクリプトは、Invoke-Command
コマンドレットを使用して 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 specializes in anything Microsoft-related and always tries to work and apply code in an IT infrastructure.
LinkedIn