コマンドレットのパラメータを列挙してみる。2011を企画しました。この記事はその2日目の記事となります。アドベントカレンダーについてはリンク先を参照してください。今日のテーマはPowerShellのバックグラウンドジョブ機能の使い方についてのまとめです。バックグラウンドジョブとはバックグラウンドジョブ機能はその名の通り、ジョブ(具体的にはスクリプト)をバックグラウンドで非同期に実行するものです。v2で追加された機能の一つです。インタラクティブシェルでStart-Jobコマンドレットを使用してバックグラウンドジョブ(以下、単に「ジョブ」と表記)を実行すると、新しくpowershell.exeのプロセスが起動しそのままシェルに制御が戻りユーザーは後続の処理を行うことができます。スクリプトからジョブを実行することも可能です。時間のかかる処理をバックグラウンドで走らせたり、数多くの処理を並列で実行したりするのに重宝します。起動されたジョブは操作中のpowershell.exeとは別のジョブ用のプロセスで実行され、処理が完了すると呼び出し元でその結果をReceive-Jobコマンドレットを使って受け取ることができます。ジョブは並列して何個も同時に実行できます。PowerShellのジョブは1ジョブ=1プロセスです。スレッドではないので注意。PowerShellのジョブシステムはリモート処理インフラストラクチャの上に構築されているので、たとえローカルPCでもジョブ実行するにはローカルPCをリモート用構成にしておく必要があります。詳しくはabout_Remote_Requirementsを参照のこと。ジョブはローカルでもリモートでも走らせることができます。以下に具体的な方法を述べていきます。ローカルコンピュータでのジョブ実行ローカルコンピュータ上に新しくジョブを作成して開始するにはStart-Jobコマンドレットを用います。{ジョブとして実行したいコマンド、スクリプト}とするとジョブを実行します。{..}のようにするとJobオブジェクト(System.Management.Automation.PSRemotingJob)を変数に格納してあとで利用できます。変数で受けない場合はJobオブジェクトの内容が表示されます。存在するジョブを取得するにはGet-Jobコマンドレットを用います。Get-Jobで現在実行中のジョブ一覧を表示します。以下に出力例を示します。120;"...以下の表は各項目の意味です。ジョブで実行されているコマンド、スクリプトジョブの終了を待つにはWait-Jobコマンドレットを用います。Get-Job|Wait-Jobとすると実行中のジョブすべてが完了するまで待ちます。-timeoutパラメータを使うと最大待ち時間(秒)を指定できます。-anyとすると実行中のいずれかのジョブが完了するまで待ちます。正確には「対象のジョブが一つ以上完了するまで待つ」という効果なので、完了済みのジョブが1つ以上ある場合に新たにジョブを追加した場合などは想定の動作になりません。Remove-Jobで完了済みのジョブを削除するか、Where-ObjectコマンドレットでRunningのみ対象にするようフィルタをかけるかしてください。ジョブを中止するにはStop-Jobコマンドレットを用います。1|Stop-JobとするとジョブIDが1のジョブを中止します。$jobにJobオブジェクトが格納されている場合は$job|Stop-JobでもOKです。ジョブを削除するにはRemove-Jobコマンドレットを用います。"Stopped"}|Remove-Jobとすると完了済みと中止したジョブを削除します。実行中のジョブは削除できませんが-forceパラメータを使って強制削除することは可能です。ジョブの実行結果データを取得するにはReceive-Jobコマンドレットを用います。Get-Job|Receive-Jobとすると完了済みのジョブのうち、結果を返却しているもの(HasMoreDataがTrueのジョブ)があればその結果を表示します。-keepパラメータをつければ結果データを保持しますが付けてない場合は参照後破棄します。*-Job系のコマンドレットの多くはJobオブジェクトを返却するので、パイプラインでどんどん繋げていけます。10|Receive-Jobのように。ジョブの基本的な使い方に関して詳しくはabout_jobsを参照してください。Frameworkのオブジェクトのイベントをサブスクライブすることができます。イベントハンドラを記述することができます。このイベントサブスクライブ機能もジョブ機能を元に構築されています。TimerオブジェクトのElapsedイベントをサブスクライブし、タイマーの実行間隔(ここでは1秒)ごとにtest.txtファイルに乱数を追記していくサンプルは次のようになります。$timer$timer.Enabled=$trueRegister-ObjectEventの結果、新しくジョブが生成しそのJobオブジェクトが返却されます。このジョブは-EventNameパラメータで指定したイベントが発生するたび、-Actionパラメータで指定したスクリプトブロックを実行します。testのように-SourceIdentifierパラメータで指定した値を指定してUnregister-Eventコマンドレットを実行することで可能です。サブスクライブを解除してもジョブ自体は削除されない(StateがStoppedになるだけ)ので、必要であればRemove-Jobで削除します。.NETオブジェクトの他にPowerShellスクリプトのカスタムイベント(Register-EngineEvent)、WMIオブジェクトのイベント(Register-WmiEvent)をサブスクライブすることもできます。これらのコマンドレットも同様にイベント発生時の処理をジョブとして登録します。詳しくは各コマンドレットのヘルプを参照してください。最初に述べたとおりPowerShellのジョブ機能はリモートインフラストラクチャの上に構築されています。よってローカルのみならずリモートコンピュータに対してジョブを実行することができます。リモートコンピュータにもリモート構成されていることが条件です。-asjobとなります。これで{}内の処理がリモートコンピュータ上のPowerShellインスタンスで実行されます。-asJobパラメータをつけることでジョブとして(ローカルPCから見て)非同期に処理できますが、-asJobパラメータを省略すると同期的に実行されます。この場合ジョブは作成されず、リモートでの処理が終了するまでローカル側は待機することになります。リモートコンピュータに接続するための資格情報を別途入力する必要がある場合は-credentialパラメータを使用します。ユーザー名とするとパスワードを入力するダイアログが表示されます。スクリプトで動かすときなどあらかじめ入力したパスワードを指定したい場合の方法は以前書きました。同じコマンドを複数のリモートPCで同時実行することも可能で、その場合は-computerNameパラメータにリモートコンピュータ名の配列を指定します(「,」区切り)。この場合ローカルPCで見えるジョブとしては1つですが、そのジョブにリモートコンピュータの数だけ子ジョブ(ChildJobs)が作成されています。子ジョブの名前とすることでリモートコンピュータごとに結果を取得できます。$job|Receive-Jobはなぜか駄目なようです。固定セッションを用いたリモーティング同じリモートPCに対して何度もコマンドを実行させたい場合、毎回リモートコンピュータ名を指定してセッションを張るのは非効率的なので、リモートセッションを確立したあとその固定セッションを何度も使用する方法が用意されています。リモートコンピュータ名とすると固定セッションが確立され、$session変数にそのセッションオブジェクトが格納されます。-asjobとすればそのたびにそのセッションを用いてリモートでコマンドを実行できるようになります。ここまでの説明はリモートコンピュータでしてきましたが、ローカルコンピュータに対して固定セッションを張ることも可能です。Enter-PSSessionコマンドレットを用いると作成したセッションに入ってリモートコンピュータ上のPowerShellを対話実行することも可能です。カレントディレクトリ>に変化し、以降リモートのPowerShellをローカルPCから対話実行できます。この状態から抜けるにはexitもしくはExit-PSSessionと入力して実行します。ジョブ実行できるそのほかのコマンドレットこれまで述べたコマンドレット以外にも、いくつかのコマンドレットはジョブ実行(ローカルorリモート)することができます。ジョブ実行するには-asJobパラメータを使用します。以下にv2の段階で-asJobパラメータが定義されているそのほかのコマンドレットを示します。Get-WmiObjectInvoke-WmiMethodRemove-WmiObjectSet-WmiInstanceTest-ConnectionRestart-ComputerStop-Computerこれらのコマンドレットはコマンドレット自体にジョブ実行機能がついているので、単独で実行するだけならStart-JobやInvoke-Commandを用いる必要がありません。v2ではWMIを扱うコマンドレットにのみ-asJobパラメータが存在するようです(ここに挙げたコマンドレットはすべてWMIの機能を呼び出すもの)。-asJobパラメータが使用できるコマンドレットの一覧を取得するのに、fsugiyamaさんの1日目の記事の問15のスクリプトを使用させていただきました。2011二日目は、PowerShellのバックグラウンドジョブ機能概要についてまとめてみました。実はバックグランドジョブ機能のTipsを書こうと思ってその前ふりとして書き始めたのですが、これだけでかなりの量になってしまったので概要だけ一記事としてまとめることにしました。PSアドベントカレンダーに私はあと何回か登場することになりそうですので、Tips編はその際に書こうと思います。明日三日目は@jsakamotoさんのご登場ですね。@mutaguchiBooks書籍版。