知る人ぞ知る「技」の使い方Windowsのスクリプト言語として、もはやなくてはならないPowerShell。普段使っているように、既存のコマンドドレッドを単純に呼び出すといったことだけでも、その便利さは十分体感できるものです。便利なのはたくさん用意されているコマンドだけではなく、知る人ぞ知る様々な「技」がたくさんあります。今回はその技の1つ、PowerShellの非同期実行の方法をご紹介します。~Hyper-Vプロビジョニング~非同期実行とは?あれこれ説明するよりも実際に見てみましょう。処理時間のかかる2つのPowerShellのコマンドの後に、テキストファイルを作成するコマンドを実行します。File通常のPowerShellの実行結果からすると、テキストファイルが実際に作成されるのは、時間のかかる二つのコマンドが実行されてから、終了するまでしばらく時間が経過した後となってしまいます。動画を再生することができませんでした。非同期で実行した場合は、スクリプト実行直後にテキストファイルが作成されます。動画を再生することができませんでした。これが非同期実行です。同期実行は複数の命令を投げた場合に、1つずつ上から順次に処理して結果が出るまで待機します。終了したら次の命令を実行してゆくことになります。非同期実行はリソースの空いている限り、命令が同時に実行されていきます。言うまでもありませんが、非同期実行の最大の効果はその処理速度です。最近のハードウェアのリソースは一度に複数の仮想化環境をサポートするくらい高性能なものとなっています。CPU、メモリ、ハードディスク、ネットワークなど、これらのリソースを使うのに、1つずつ仕事をさせるというのではとてももったいない使い方です。ハードウェアの本領が発揮されません。リソースがゆるすかぎりたくさんの仕事をさせてこそ本当の実力が分かります。非同期実行とはいっても、命令の渡し方にしても、CPUだけ、ハードディスクだけといったように一つのリソースに偏るような命令の渡し方ではなく、まんべんなく偏りのない命令の渡し方というのもポイントになります。PowerShellの非同期実行といっても、方法は一つだけではなく、いくつか方法があります。Workflow」「asyncとawait」などがあります。Namespace」の「RunspacePoolクラス」を利用したPowerShellの非同期実行の方法を紹介します。RunspacePoolの中で実行されたPowerShellのコマンドは非同期に実行することが可能になります。PowerShellサンプルまずは具体的なコードです。}上から見ていきましょう。AsyncPowershellという関数に、配列文字列として複数のPowerShellのコマンドを渡しています。作って、開いて利用します。finallyで確実に一度開いたRunspacePoolを使い終わったら必ず閉じるようにしておきます。開きっぱなしにしておくと、いつかリソースが枯渇してしまいRunspacePoolを開くことができなくなってしまうのでご注意を。RunspacePoolを作成します。引数として渡したコマンドの数だけRunspacePoolを作成し$RunspacePoolに格納します。最小値を1、最大値を実行させたいコマンド数としています。RunspacePoolを作成して実行することもできますが、この場合処理速度がやや遅くなります。RunspacePoolが実行したい命令数より少ない場合は同期処理と同じようにRunspacePoolが空き次第、次の命令を実行ということになります。非同期処理のメリットを最大限に発揮するには、あらかじめRunspacePoolの数を不足ないように設定して実行する必要があります。この2つのArrayListは、それぞれのPowerShellコマンドとその実行結果を格納するために定義します。出力するために利用します。}で引数で渡されたコマンドを1つずつ実行していきます。コマンドの実行は、System.Management.Automation.PowerShellクラスから行います。FrameworkからPowerShellのコマンドを実行するためのクラスです。Frameworkのクラスとして提供されているので、System.Management.Automation.Runspacesクラス同様、もちろんVBやC#からも利用することが可能です。[PowerShell]::Create()でPowerShellのオブジェクトを作成します。$PowerShell.RunspacePoolには先に定義した$RunspacePoolを指定します。これによってPowerShellのコマンドがRunspacePool内で非同期に実行されます。AddScriptで実行するコマンドを指定します。実行結果としての戻り値をテキストとして取得できるようにパイプラインとして追加しておきます。BeginInvokeでコマンドを実行して、実行結果としてIAsyncResultを取得して$aryIAsyncResultに格納します。$aryPowerShellの中には実行したPowerShellオブジェクトが格納されています。このwhileの中で実行したコマンドの結果を取得します。実行結果を取得し次第、$aryPowerShellから1つずつPowerShellオブジェクトを削除してゆき、最終的に$aryPowerShellが空になれば終了となります。実行結果は非同期実行の場合は順番に取得するのではなく、終了したものから随時取得していきます。$aryIAsyncResultには実行結果が格納されています。$aryIAsyncResult[$i]を確認します。実行結果を取得するごとに、if($IAsyncResult.IsCompleted)でコマンドが終了したかどうかを判断しています。$Resultで実行結果を出力します。終了したPowerShellオブジェクトと実行結果オブジェクトは削除して、再度ループに入ります。$aryPowerShellが空になるまで繰り返されます。大まかな処理の流れです。RunspacePoolを閉じる非同期実行のポイントRunspacePoolを使ってのPowerShellのコマンド実行は、まず、すべてのコマンドをRunspacePool内で起動さてしまうこと。すべて起動し終わってから、コマンドの実行結果は、Loopで実行状態を確認しつつ、随時取得してゆくという部分になります。BeginInvokeの直後に、EndInvokeをしてしまうと、同期実行と同様に、一つのコマンドが終了するまで、待機状態になってしまうのでご注意ください。以上、ご紹介したのは、ローカルで実行する場合のサンプルとなります。PowerShellの非同期実行はもちろんリモートからでも可能となっています。}リモート実行で異なるのは、RunspacePoolに認証情報を追加する部分だけです。呼び出す関数に、実行対象のサーバー名、アカウント、パスワードの引数を追加しています。ConvertTo-SecureStringでパスワードをセキュア状態に変更してから、System.Management.Automation.Runspaces.WSManConnectionInfoのConnectionInfoオブジェクトを作成して、Credentialとして引き渡します。CreateRunspacePoolの第三の引数として、ConnectionInfoオブジェクトを指定して、RunspacePoolを作成してOpenします。これでリモートでの非同期実行の準備が完了しました。クラスを利用して実現しています。従ってVBやC#からもPowerShellのコマンドを非同期で実行することが可能です。この最大のメリットは、筆者の守備範囲であるHyper-Vのプロビジョニングにおいて発揮されます。Hyper-VのプロビジョニングはすべてWMIをつかってVisualStudioで開発することが可能です。簡単なPowerShellで、かつ、開発効率のよいVisualStudioを使ってプロビジョニングシステムを開発したいというのは当然の発想といえます。そこで、System.Management.Automation.PowerShellクラスを利用して、VisualStudioでVBやC#からPowerShellのコマンドを実行させます。Hype-Vの操作には時間のかかる操作がいくつかあります。仮想マシンのエクスポートや、LiveMigrationがこれに該当します。数十ギガにおよぶディスクのコピーが発生する場合は、高速な共通ストレージなどが無い環境では相当な時間を要するものになります。クラスを利用したPowerShellの非同期実行なのです。VBとC#のサンプルも紹介しておきます。時間のかかる仮想マシンのエクスポートと当時に、他の仮想マシンを起動しつつ、Hyper-V上の仮想マシン一覧情報を取得しています。}以上、今回は知る人ぞ知る、PowerShellの「技」の一つをご紹介しました。PowerShellの非同期実行によって、より効率的なサーバー管理などにの役立てていただければ幸いです。PowerShellとVisualStudioによるHyper-Vプロビジョニングにも是非お試しください。サンプルコードをこちらからダウンロードいただけます。PackとHyper-Vを利用し、企業内IaaS(仮想マシン提供サービス)を構成するための、IT管理者に向けた手引書です。試用したサーバーは、最小限度の物理サーバーと仮想マシンで構成しています。Packに必要なコンポーネントのダウンロード、実際にプライベートクラウド構築する過程を、手順を追って解説しています。これからプライベートクラウドの構築を検討するうえで、作業負担の軽減に役立つ一冊です。勝一GMOインターネット株式会社1999年6月GMOインターネットに入社。Windowsを用いたホスティング事業の立ち上げの際、サービス開発からその後の保守・運用まで1人で担当。2010年には「お名前.comWindowsデスクトップ」をリリースし、マイクロソフト社と強い信頼関係を構築。