そもそもジョブとは何?
コマンドをバックグラウンドで実行するとき、PowerShellでは、「ジョブ」オブジェクトを使って、バックグラウンド実行を表現する。コマンドをバックグラウンド実行すると、ジョブオブジェクトが作られ、このオブジェクトに対して操作を行うことで、実行を停止させる、あるいは状態を調べることができる。ジョブの状態はStateプロパティが表わす。
Stateプロパティを確認するにはGet-Jobコマンドを使う。なお、バックグラウンドジョブは、停止させることは可能だが、中断させることや停止したジョブを再開させることはできない。Running、Completed以外の場合、実行が失敗あるいは他の理由でバックグラウンドジョブは停止している。再実行させるには同じStart-Jobコマンドを実行するしかない。
バックグラウンド演算子やStart-Jobコマンドで起動するジョブを「Background Job」という。これは複数あるPowerShellジョブの1つだ。
そのほか、WorkflowやCIMJobなどもあるが、特定目的のオブジェクト処理に関するものであり、ここでは解説しない。スケジュールジョブは、タスクスケジューラーのタスクをPowerShellのジョブとして扱うものだ。ここでは、バックグラウンドジョブとスレッドジョブのみを扱う。
ジョブは、実行中のPowerShellとは別プロセスで起動されるため、ジョブコマンドからは実行中のPowerShellにある変数や関数などにアクセスできない。同様にジョブコマンド側で変数に定義しても、PowerShell側に持ち込むこともできない。
関数定義や変数へのアクセスが必要になる場合、-InitializationScriptオプションや-ArgumentListオプションを使って必要な情報を渡す。-InitializationScriptオプションを使うと、ジョブコマンドで利用できる関数を定義することができる。
Start-Job -InitializationScript {function mydir($x){ Get-ChildItem $x }} { mydir "D:\temp" }
-ArgumentListオプションを使うことで、ジョブコマンドに引数を与えることができる。
ただし、スクリプトブロック内でParmステートメントを使って受け取る引数を定義しておく必要がある。
$mypath="D:\temp"
start-job -ScriptBlock { param($p); dir $p } -ArgumentList $mypath
実行結果を受け取る場合には、ジョブコマンドは代入文とせず実行するだけにしてReceive-Jobコマンドの出力を変数に代入する。ただし、-keepオプションを付けないで実行するとその時点の実行結果は消えてしまう。これは、長い実行時間の間に散発的に出力を行うようなコマンドの場合、-keepオプションを付けないReceive-Jobを繰り返すことで最新の出力のみを受け取り可能にするためだ。
Start-Job -ScriptBlock { dir }
$r=Receive-Job -id <ジョブID>
バックグラウンドジョブが終了し、結果も受け取って用済みとなったときには、Remove-Jobで削除することができる。すべてのジョブを削除したいときには、
Get-Job | Remove-Job
とする。
スレッドジョブ
スレッドジョブは、現在のPowerShellと同じプロセス内で、スレッドとして実行される。バックグラウンドジョブは、別プロセスを起動するため起動に時間がかかり、メモリなどのリソースを消費する。大量のジョブを並列実行させたときには、起動時間のオーバーヘッドが大きくなる。
スレッドジョブは、プロセスを生成しないので高速に起動する。しかし、スレッドジョブはジョブコマンド側のエラーが実行中のPowerShellに影響を与える可能性があり、最悪、ジョブコマンドとともにクラッシュする可能性がある。
速度を取るか、安全性を取るかといった問題だが、単純な外部コマンドなどの実行であれば、起動のオーバーヘットはそれほど問題にならないので、わざわざスレッドジョブを使う必要はないだろう。スレッドジョブは、クラッシュする危険がないコマンドを大量に並行実行させるときに使う。
スレッドジョブは、起動にStart-ThreadJobコマンド(https://learn.microsoft.com/ja-jp/powershell/module/threadjob/start-threadjob)を用いる以外は、バックグラウンドジョブと同じで、他のバックグラウンドジョブ用のコマンド(Get-Jobなど)をそのまま使う。また、起動オプションに関しても共通して使えるものがある。
ただし、PowerShell環境としては分離されている(PowerShellのRunspaceを使っている)ため、バックグラウンドジョブと同じく、実行中のPowerShellで定義した関数や変数をジョブコマンドで直接利用できない。Start-Jobと同じく-InitializationScriptオプションや、-ArgumentListオプションを使って必要な情報を渡す。
かなり時間のかかるUpdate-Helpコマンド(https://learn.microsoft.com/ja-jp/powershell/module/microsoft.powershell.core/update-help)などもバックグラウンドで処理すれば終了を待つ必要もない。
PowerShellのバックグラウンド実行には制限も多いが、内部コマンドだけ、あるいは外部コマンドなら、あまり気にする必要はない。自作の関数があるときや変数でパラメーターを指定しているときのみ注意すればよい。
この連載の記事
-
第460回
PC
Windowsでsftpを使う -
第459回
PC
WSL 2.4.4ではtar形式でのディストリビューションが配布でき、企業での利用が容易になってきた -
第458回
PC
Windows上でhostsファイルを活用する -
第457回
PC
IPv6アドレスは先頭を見ればどんな種類かわかる -
第456回
PC
あらためてIPv6基本のキ -
第455回
PC
Windowsで現在どのネットワークアダプタがインターネット接続に使われているかを調べる方法 -
第454回
PC
Windows 11 24H2では「デバイスの暗号化」の条件が変わり、より多くのPCでドライブが暗号化される -
第453回
PC
Windows 11 24H2の配布開始後もすぐにはやってこない Windows UpdateとSafeguard Holds -
第452回
PC
Windows 11 Ver.24H2が登場 Copilot+ PCとそうでないPCで実質Windowsが2つに分かれる -
第451回
PC
新しいWindowsサンドボックスではコマンドラインからの制御が可能に -
第450回
PC
ユニコードで文字数を数える方法 - この連載の一覧へ