Windows PowerShell: リモート処理について

リモート処理は Windows PowerShell の最も強力な側面の 1 つなので、詳しく見てみる価値があります。

Don Jones

リモート処理は、Windows PowerShell の最も有益で注目に値する機能の 1 つです。今月のコラムでは、リモート処理とそのしくみを詳しく説明します。また、Windows PowerShell を効率的で価値のある生産性ツールにするいくつかの方法を考えてみましょう。

リモート処理について

まず、リモート処理を使用するには、対象となるコンピューターでリモート処理を有効にする必要があることを覚えておいてください。リモート処理を有効にするには、対象となるコンピューターで Enable-PSRemoting コマンドレットを実行するか、グループ ポリシー経由でリモート処理を構成します。Windows PowerShell 2.0 で「help about_remote_troubleshooting」というコマンドを実行して、指示を確認できます。

リモート処理を実行するには Windows PowerShell 2.0 がインストールされている必要があります。Windows XP 以降の任意のバージョンの Windows に対応したバージョンは、マイクロソフト Web サイトからダウンロードできます。また、リモート処理が有効になっているコンピューターでは、 TCP ポートが開かれます。Windows ファイアウォールを使用している場合は、Enable-PSRemoting コマンドレットを実行すると、必要なファイアウォール接続が自動的に作成されます。

1 対 1 のリモート処理

リモート処理を使用する最も簡単な方法は、Unix や Linux システムで Secure SHell (SSH) を使用するのと同じように、対話型のシェルとして使用することです。「Enter-PSSession –computername <サーバー>」というコマンドを実行します (<サーバー> には、リモート コンピューターの名前を指定します)。

この際、エイリアスや IP アドレスではなく、コンピューターの実際の名前を使用する必要があります。リモート処理が有効になっていれば、このコマンドはドメイン環境で動作し、Kerberos を使用して、リモート処理を実行するコンピューターとリモート コンピューターが相互に認証されます。非ドメイン環境では、about_remote_troubleshooting ヘルプ トピックでコンピューターの構成に関する指示を確認してください。

コマンドの実行に使用している資格情報がリモート コンピューターに委任されることに注意してください。リモート コンピューターで実行するコマンドは、使用中の資格情報で実行されるので、強力なシステム アカウントで実行されることはありません。ただし、複数のホップで資格情報を委任することはできないので、通常、リモート シェル プロンプトを開いているときに、別のコンピューターに対してリモート処理を実行することはできません。接続を閉じて、ローカル コンピューターに戻るには、Exit-PSSession コマンドレットを実行します。

1 対多のリモート処理

リモート処理の真の実力は、コマンドを 1 台以上のリモート コンピューターに同時に送信できることです。各リモート コンピューターでコマンドが実行され、結果のオブジェクトが XML 形式でシリアル化され、結果がネットワーク経由で処理元のコンピューターに返されます。

処理元のコンピューターでは、XML を受け取ってシリアル化を解除して、静的なオブジェクトに戻します。この動作により、リモートで実行したコマンドの出力を他のコマンドの出力とほぼ同じように処理できるようになります。

すべての処理は、Invoke-Command コマンドレットで始まります。最も簡単な方法は、実行するコマンドをスクリプト ブロックの形式で指定し、そのコマンドを実行する対象となる 1 台以上のコンピューターを指定するだけです。たとえば、各行に 1 台のコンピューター名が記載されているテキスト ファイルからコンピューター名の一覧を読み取って、各コンピューターでコマンドを実行するには、次のコマンドを実行します。

Invoke-Command –scriptblock { Get-EventLog Security –newest 200 }

–computername (Get-Content computernames.txt)

結果が処理元のコンピューターに返されると、結果には PSComputerName というプロパティが追加されています。このプロパティから、どれがどのコンピューターの結果であるかを特定できます。コマンドの実行結果は同じ順序で返されるとは限らないので、この情報は役立ちます。

リモート コンピューターで実行したコマンドの出力を受け取ったら、このプロパティを使用して、出力に対して並べ替え、グループ化、フィルターなどの操作を行えます。Sort-Object コマンドレットでは、並べ替えを実行するためにメモリ内にすべての出力をキャッシュしなければならないので、膨大な量のデータが返されたときにデータを並べ替えることは避けてください。

Invoke-Command コマンドレットでも –FilePath パラメーターがサポートされています。–ScriptBlock の代わりに、このパラメーターを使用して、少数のコマンドを実行するのではなく、実行するスクリプトを指定できます。他にも、さまざまな資格情報を指定したり、既定値をオーバーライドできるパラメーターがあります。

  • –Credential: ユーザー名を指定できます。実行時にはパスワードの入力が求められます。この資格情報を使用して、リモート コンピューターに接続し、コマンドやスクリプトを実行します。Get-Credential コマンドレットを使用して作成した Credential オブジェクトを渡すこともできます。
  • –Port: 既定以外のポートを指定できます。このパラメーターは、基盤となる Windows Remote Mangament (WinRM) サービスが別のポートをリッスンするように再構成されている場合に使用します。
  • –UseSSL: 接続の暗号化と別の TCP ポートの使用を強制します (HTTPS で、暗号化されていない HTTP と異なるポートを使用するのと同じ方法で実施します)。
  • –ThrottleLimit: 同時に接続できるコンピューターの既定値 (既定値は 32) を変更できます。この既定値は、比較的大きな環境でテストし問題がないことが確認されています。この値を上げると、コンピューターで、より多くのプロセッサとメモリを消費することになるので、このパラメーターを使用する場合には注意してください。

リモート コマンドに入力を指定する

Invoke-Command コマンドレットには、見過ごされがちなパラメーターが 2 つあります。1 つ目は -ArgumentList です。このパラメーターを併用できるのは -ScriptBlock のみです (-FilePath パラメーターと併用することはできません)。-ArgumentList パラメーターは、コンピューターのローカル変数をリモート コンピューターに送信するコマンドに渡すように設計されています。

スクリプト ブロックでは、リモート コンピューターで使用する変数を宣言するパラメーター ブロックを定義します。-ArgumentList パラメーターで指定した値は、この変数に渡されます。次に例を示します。

Invoke-Command –computername SERVER1 –scriptblock { param($one,$two) Get-EventLog –logname $one –newest $two } –ArgumentList $log,$quantity

この例では、スクリプトは、ローカル変数 $log の内容を $one 変数に渡し、この変数を使用して受け取ったログ名を定義します。次に、ローカル変数 $quantity の内容を $two 変数に渡し、この変数を使用して、受け取ったイベント ログ エントリの数を定義します。引数を渡す作業は、順番に行われます。$log と $one は、どちらも先にリストされているので前者の内容が後者に渡されます。$quantity と $two は、どちらも 2 つ目にリストされているので、前者の内容が後者に渡されます。

2 つ目は -InputObject パラメーターです。このパラメーターを使用しても、リモート コンピューターに入力を指定することができます。これは、-ScriptBlock と -FilePath のどちらとでも機能します。-InputObject パラメーターに指定したオブジェクトが、リモート コマンドまたはスクリプトで使用されている $input という名前の特殊な変数に渡されます。

リモート コマンドの出力を取得する

Get-EventLog などの単一のシンプルなコマンドを実行していると仮定すると、このコマンドの出力は Invoke-Command コマンドレットから返されます。たとえば、後で使用できるように、出力のすべてのコンテンツを XML ファイルにダンプするには、次のコマンドを使用します。

Invoke-Command –computername ONE,TWO,THREE –scriptblock { Get-EventLog Security –newest 100 } | Export-CliXML results.xml

リモート コンピューターでスクリプトを実行している場合、スクリプトでは、結果としてオブジェクト (できれば、1 種類のオブジェクト) を生成する必要があります。たとえば、次のスクリプトは、-InvokeCommand コマンドレットの -FilePath パラメーターを経由してリモート コンピューターに送信されるように設計されています。このスクリプトで新しいオブジェクトを作成し、2 つのローカル オブジェクトの情報を組み合わせている方法に注目してください。組み合わされたカスタム オブジェクトは、パイプラインへの出力で、この出力は Invoke-Command コマンドレットを実行したコンピューターに転送されます。コマンドは、次のとおりです。

$os = Get-WmiObject –class Win32_OperatingSystem

$bios = Get-WmiObject –class Win32_BIOS

$obj = New-Object –TypeNamePSObject

$obj | Add-Member NotePropertyOSVersion $os.caption

$obj | Add-Member NotePropertyBIOSSerial $bios.serialnumber

Write-Output $obj

PSComputerName プロパティが自動的に追加されるので、どれがどのコンピューターの結果であるかを特定できます。このように 1 種類のオブジェクトを出力すると、Windows PowerShell の他の機能と最も高い互換性が実現できるので、リモートで実行したスクリプトの出力を送信する場合のベスト プラクティス的な方法であることに間違いありません。

Don Jones

Don Jones は、Microsoft MVP の受賞者で、『Learn Windows PowerShell in a Month of Lunches』(Manning Publications Co.、 2010 年) の著者でもあります。この書籍は、管理者が Windows PowerShell を効率的に使用できるようにすることを目的としています。また、一般ユーザーを対象にオンサイトの Windows PowerShell トレーニングも開催しています。Don に対するお問い合わせについては、彼の Web サイト (ConcentratedTech.com、英語) を参照してください。

関連コンテンツ