GUIを使っていると、マルチタスクという意識もなく、複数のアプリケーションをウィンドウで扱っている。実際には、アクティブでないウィンドウ(のアプリケーション)は、バックグラウンド実行になる。
コンソールでシェルを使う場合、複数タスクの実行は、ユーザーが「ジョブ(タスク)」を意識して、ジョブコマンドを使って実行する必要がある。とはいえ、ターミナルでのシェルの利用は、コンピュータ利用の初期からあったものだ。マルチタスクに対応したオペレーティングシステムでは、コンソールからのマルチタスク実行に対してさまざまな仕組みが「シェル」に組み込まれた。その1つの完成形がBSD系UNIXに搭載されたCシェルに組み込まれた「ジョブコントロール」だ。このコマンドは、BSDジョブコントロールとも呼ばれていたが、bashなどに取り込まれ、標準的なものとなった(表01)。
Windowsの標準シェルであるPowerShellにも、ジョブ(JOB)コマンドがある(表02)。PowerShellの場合、実行中のコマンドラインやスクリプトを再開可能な形で「中断」する機能がない。
ただ、PowerShellというか、Windowsの場合、時間のかかるコマンドは、ストレージ関連もしくはプリンタ出力程度であり、それ以外の処理は、比較的短時間で終わる。というのも、PowerShellでは、パイプラインでオブジェクトの配列を流すようになっている。要素ごとに処理を並列化する仕組みがあるため、よほど面倒な繰り返し計算でもさせない限り、コマンドラインの実行は短時間で終了する。
結果的にいうと、PowerShellでのジョブ使い方としては、最初からコマンドをバックグラウンド実行させ、必要に応じて、結果(コマンド出力)を取得するという手順になる。UNIX/LINUX系と異なり、PowerShellは、バックグラウンド実行のコマンド出力は、抑制されており、Receive-Jobコマンドを使って、コマンド出力を取得する。バックグラウンド実行には、Start-Jobコマンドもあるが、コマンド末尾に“&”を付ける方法も使える。
こうした場合に必要になるのが、Start-Jobコマンドなどが戻り値とするPSRemotingJobオブジェクトだ。ここには、バックグラウンドジョブに関する情報があり、JOB関連コマンドと組み合わせることで、該当のバックグラウンドジョブの制御が行える。PSRemotingJobは、作成順に増加していく整数値のIdプロパティがある。これは、Stop-Jobなどの制御コマンドの引数として指定できる。
バックグラウンドジョブは、子プロセスではなく、別プロセスとなるため、起動したコマンドライン側変数などのコンテキストを持たずに起動する。コマンドライン側の変数を参照する必要があるなら、コマンドの引数として変数を指定して渡す必要がある。たとえば、以下のようなコマンドを使う(写真01)。
$a="Shioda"
$myjob = Start-Job -ScriptBlock { Write-Output "==$($args)==" } -ArgumentList $a; Start-Sleep -Milliseconds 500; Receive-Job $myjob
-

写真01: 起動側の変数などをバックグラウンドジョブで扱うには、Start-Jobのスクリプトブロックの引数として変数を渡す必要がある。ジョブを起動したあと、少し待ってから、Receive-Jobでスクリプトブロックの出力を受け取る
ここで、Start-Sleepコマンドは、バックグラウンドでプロセスを作り、スクリプトブロックを実行し終わるまで、Receive-Jobコマンドを遅らせるために入れてある。
また、$myjobには、Start-Jobコマンドの結果として、前述のPSRemotingJobgが入っている。Receive-Jobはこれを使うことで結果を受け取ることが可能だ。
PowerShellのPSRemotingJobオブジェクトは、ジョブが終了したあとも残り続け、Remove-Jobコマンド(これもまたIdを受け付ける)で明示的に削除する必要がある。
今回のタイトルネタは、エドガー・ライス・バローズ(Edgar Rice Burroughs)の火星シリーズの一作、「火星の幻兵団」(東京創元社。原題Thuvia, Maid of Mars、1920)である。原題は、「火星の乙女、トゥビア」という意味(日本語版ではサビア)。「火星のプリンセス」のデジャー・ソリスに続く火星第2のプリンセスである。


