about_Jobs
簡単な説明
PowerShell バックグラウンド ジョブが現在のセッションと対話せずにバックグラウンドでコマンドまたは式を実行する方法について説明します。
長い説明
PowerShell は、ジョブを介してコマンドとスクリプトを同時に実行します。 同時実行をサポートするために PowerShell によって提供されるジョブの種類は 3 つあります。
RemoteJob
- コマンドとスクリプトはリモート セッションで実行されます。 詳細については、「 about_Remote_Jobs」を参照してください。BackgroundJob
- コマンドとスクリプトは、ローカル コンピューター上の別のプロセスで実行されます。PSTaskJob
またはThreadJob
- コマンドとスクリプトは、ローカル コンピューター上の同じプロセス内で別のスレッドで実行されます。 詳細については、「 about_Thread_Jobs」を参照してください。
スクリプトを別のコンピューターまたは別のプロセスでリモートで実行すると、優れた分離が実現されます。 リモート ジョブで発生したエラーは、実行中の他のジョブやジョブを開始した親セッションには影響しません。 ただし、リモート処理レイヤーでは、オブジェクトのシリアル化など、オーバーヘッドが増加します。 親セッションとリモート (ジョブ) セッションの間で渡されると、すべてのオブジェクトがシリアル化および逆シリアル化されます。 大規模な複雑なデータ オブジェクトのシリアル化では、大量のコンピューティング リソースとメモリ リソースが消費され、大量のデータがネットワーク経由で転送される可能性があります。
スレッド ベースのジョブは、異なるスレッドで同じプロセスで実行されるため、リモート ジョブとバックグラウンド ジョブほど堅牢なわけではありません。 1 つのジョブに重大なエラーが発生してプロセスがクラッシュした場合、プロセス内の他のすべてのジョブは終了します。
ただし、スレッドベースのジョブでは、オーバーヘッドが少なくて済みます。 リモート処理レイヤーやシリアル化は使用しません。 結果オブジェクトは、現在のセッションのライブ オブジェクトへの参照として返されます。 このオーバーヘッドがなければ、スレッドベースのジョブの実行速度が速くなり、他のジョブの種類よりも少ないリソースが使用されます。
重要
ジョブを作成した親セッションも、ジョブの状態を監視し、パイプライン データを収集します。 ジョブの子プロセスは、ジョブが完了状態に達すると、親プロセスによって終了されます。 親セッションが終了すると、実行中のすべての子ジョブが子プロセスと共に終了します。
この状況を回避するには、次の 2 つの方法があります。
- を使用して
Invoke-Command
、切断されたセッションで実行されるジョブを作成します。 詳細については、「 about_Remote_Jobs」を参照してください。 - を使用して
Start-Process
、ジョブではなく新しいプロセスを作成します。 詳細については、「Start-Process」を参照してください。
ジョブ コマンドレット
Start-Job
- ローカル コンピューターでバックグラウンド ジョブを開始します。Get-Job
- 現在のセッションで開始されたバックグラウンド ジョブを取得します。Receive-Job
- バックグラウンド ジョブの結果を取得します。Stop-Job
- バックグラウンド ジョブを停止します。Wait-Job
- 1 つまたはすべてのジョブが完了するまで、コマンド プロンプトを抑制します。Remove-Job
- バックグラウンド ジョブを削除します。Invoke-Command
- AsJob パラメーターは、リモート コンピューター上にバックグラウンド ジョブを作成します。 を使用Invoke-Command
して、 を含むStart-Job
任意のジョブ コマンドをリモートで実行できます。
ローカル コンピューターでジョブを開始する方法
ローカル コンピューターでバックグラウンド ジョブを開始するには、 コマンドレットを Start-Job
使用します。
コマンドを Start-Job
記述するには、ジョブが実行するコマンドを中かっこ ({}
) で囲みます。 コマンドを指定するには、 ScriptBlock パラメーターを使用します。
次のコマンドは、ローカル コンピューターでコマンドを Get-Process
実行するバックグラウンド ジョブを開始します。
Start-Job -ScriptBlock {Get-Process}
バックグラウンド ジョブを開始すると、ジョブの完了に長時間かかる場合でも、コマンド プロンプトはすぐに返されます。 ジョブの実行中は、中断されることなく引き続きセッションで作業できます。
コマンドは Start-Job
、ジョブを表す オブジェクトを返します。 ジョブ オブジェクトにはジョブに関する有用な情報が含まれていますが、ジョブの結果は含まれません。
ジョブ オブジェクトを変数に保存し、他の Job コマンドレットと共に使用してバックグラウンド ジョブを管理できます。 次のコマンドは、ジョブ オブジェクトを開始し、結果のジョブ オブジェクトを 変数に $job
保存します。
$job = Start-Job -ScriptBlock {Get-Process}
PowerShell 6.0 以降では、パイプラインの末尾にあるバックグラウンド演算子 (&
) を使用してバックグラウンド ジョブを開始できます。 詳細については、「 バックグラウンド演算子」を参照してください。
バックグラウンド演算子の使用は、前の例の コマンドレットの Start-Job
使用と機能的に同じです。
$job = Get-Process &
ジョブ オブジェクトの取得
コマンドレットは Get-Job
、現在のセッションで開始されたバックグラウンド ジョブを表すオブジェクトを返します。 パラメーターを指定しないと、 Get-Job
現在のセッションで開始されたすべてのジョブが返されます。
Get-Job
ジョブ オブジェクトには、ジョブが完了したかどうかを示すジョブの状態が含まれます。 完了したジョブの状態が [完了] または [失敗] です。 ジョブが ブロック または 実行中である場合もあります。
Id Name PSJobTypeName State HasMoreData Location Command
-- ---- ------------- ----- ----------- -------- -------
1 Job1 BackgroundJob Complete True localhost Get-Process
ジョブ オブジェクトを変数に保存し、それを使用して後のコマンドでジョブを表すことができます。 次のコマンドは、ID 1 のジョブを取得し、変数に $job
保存します。
$job = Get-Job -Id 1
ジョブの結果の取得
バックグラウンド ジョブを実行すると、結果はすぐには表示されません。 バックグラウンド ジョブの結果を取得するには、 コマンドレットを使用します Receive-Job
。
次の例では、 コマンドレットは Receive-Job
、 変数の job オブジェクトを使用してジョブの結果を $job
取得します。
Receive-Job -Job $job
Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName
------- ------ ----- ----- ----- ------ -- -----------
103 4 11328 9692 56 1176 audiodg
804 14 12228 14108 100 101.74 1740 CcmExec
668 7 2672 6168 104 32.26 488 csrss
...
ジョブの結果を変数に保存できます。 次のコマンドは、ジョブの結果を変数$results
に$job
保存します。
$results = Receive-Job -Job $job
部分的なジョブ結果の取得と保持
コマンドレットは Receive-Job
、バックグラウンド ジョブの結果を取得します。 ジョブが完了した場合は、 Receive-Job
すべてのジョブ結果を取得します。 ジョブがまだ実行されている場合は、 Receive-Job
これまでに生成された結果を取得します。 コマンドをもう一度実行 Receive-Job
して、残りの結果を取得できます。
既定では、 Receive-Job
ジョブの結果が格納されているキャッシュから結果を削除します。 もう一度実行すると、最初の実行 Receive-Job
後に到着した新しい結果のみが取得されます。
次のコマンドは、ジョブが完了する前に実行されるコマンドの Receive-Job
結果を示しています。
C:\PS> Receive-Job -Job $job
Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName
------- ------ ----- ----- ----- ------ -- -----------
103 4 11328 9692 56 1176 audiodg
804 14 12228 14108 100 101.74 1740 CcmExec
C:\PS> Receive-Job -Job $job
Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName
------- ------ ----- ----- ----- ------ -- -----------
68 3 2632 664 29 0.36 1388 ccmsetup
749 22 21468 19940 203 122.13 3644 communicator
905 7 2980 2628 34 197.97 424 csrss
1121 25 28408 32940 174 430.14 3048 explorer
返されるジョブの結果を削除しないようにReceive-Job
するには、Keep パラメーターを使用します。 次のコマンドは、まだ完了していないジョブで Keep パラメーターを使用した場合の影響を示しています。
C:\PS> Receive-Job -Job $job -Keep
Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName
------- ------ ----- ----- ----- ------ -- -----------
103 4 11328 9692 56 1176 audiodg
804 14 12228 14108 100 101.74 1740 CcmExec
C:\PS> Receive-Job -Job $job -Keep
Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName
------- ------ ----- ----- ----- ------ -- -----------
103 4 11328 9692 56 1176 audiodg
804 14 12228 14108 100 101.74 1740 CcmExec
68 3 2632 664 29 0.36 1388 ccmsetup
749 22 21468 19940 203 122.13 3644 communicator
905 7 2980 2628 34 197.97 424 csrss
1121 25 28408 32940 174 430.14 3048 explorer
結果の待機中
完了に長い時間がかかるコマンドを実行する場合は、ジョブ オブジェクトのプロパティを使用して、ジョブが完了したタイミングを判断できます。 次のコマンドでは、 オブジェクトを Get-Job
使用して、現在のセッションのすべてのバックグラウンド ジョブを取得します。
Get-Job
結果はテーブルに表示されます。 ジョブの状態が [ 状態 ] 列に表示されます。
Id Name PSJobTypeName State HasMoreData Location Command
-- ---- ------------- ----- ----------- -------- -------
1 Job1 BackgroundJob Complete True localhost Get-Process
2 Job2 BackgroundJob Running True localhost Get-EventLog -Log ...
3 Job3 BackgroundJob Complete True localhost dir -Path C:\* -Re...
この場合、 State プロパティはジョブ 2 がまだ実行されていることを示します。 コマンドレットを使用 Receive-Job
してジョブの結果を取得すると、結果は不完全になります。 コマンドレットを Receive-Job
繰り返し使用して、すべての結果を取得できます。 State プロパティを使用して、ジョブが完了したタイミングを確認します。
コマンドレットの Wait パラメーターを Receive-Job
使用することもできます。 このパラメーターを使用すると、ジョブが完了し、すべての結果が使用可能になるまで、コマンドレットはコマンド プロンプトを返しません。
コマンドレットを使用して、 Wait-Job
ジョブの結果の一部またはすべてを待機することもできます。 Wait-Job
では、1 つ以上の特定のジョブまたはすべてのジョブを待機できます。
次のコマンドでは、 コマンドレットを Wait-Job
使用して 、ID 10 のジョブを待機します。
Wait-Job -ID 10
その結果、ジョブが完了するまで PowerShell プロンプトは抑制されます。
また、所定の期間待つこともできます。 このコマンドでは、 Timeout パラメーターを使用して待機を 120 秒に制限します。 時間が経過すると、コマンド プロンプトが返されますが、ジョブはバックグラウンドで引き続き実行されます。
Wait-Job -ID 10 -Timeout 120
ジョブの停止
バックグラウンド ジョブを停止するには、 コマンドレットを使用します Stop-Job
。 次のコマンドは、システム イベント ログ内のすべてのエントリを取得するジョブを開始します。 ジョブ オブジェクトを 変数に $job
保存します。
$job = Start-Job -ScriptBlock {Get-EventLog -Log System}
次のコマンドは、ジョブを停止します。 パイプライン演算子 (|
) を使用して、変数内のジョブを $job
に Stop-Job
送信します。
$job | Stop-Job
ジョブの削除
バックグラウンド ジョブを削除するには、 コマンドレットを使用します Remove-Job
。 次のコマンドは、 変数内のジョブを $job
削除します。
Remove-Job -Job $job
失敗したジョブの調査
ジョブは、さまざまな理由で失敗する可能性があります。 ジョブ オブジェクトには、エラーの原因に関する情報を含む Reason プロパティが含まれています。
次の例では、必要な資格情報なしでジョブを開始します。
$job = Start-Job -ScriptBlock {New-Item -Path HKLM:\Software\MyCompany}
Get-Job $job
Id Name PSJobTypeName State HasMoreData Location Command
-- ---- ------------- ----- ----------- -------- -------
1 Job1 BackgroundJob Failed False localhost New-Item -Path HKLM:...
Reason プロパティを調べて、ジョブの失敗の原因となったエラーを見つけます。
$job.ChildJobs[0].JobStateInfo.Reason
この場合、リモート コンピューターがコマンドを実行するために明示的な資格情報を必要としたため、ジョブは失敗しました。 Reason プロパティには、次のメッセージが含まれています。
リモート サーバーへの接続が失敗し、"アクセスが拒否されました" というエラー メッセージが表示されました。