• マイクロソフトの IT コンシューマライゼーション 全体像 3

    前回までの投稿は以下の通りです。

    3.2 どこからでも接続 ~ 個人のデバイスから社内に接続する①

    個人デバイスとしては、通常のノートPC、そしてタブレット、スマートフォンが挙げられますが、ここではノートPCとタブレットを軸にお話ししたいと思います。

    BYOD(Bring Your Own Device)という言葉がはやっているように、個人のデバイスを業務で使用したいという要望が大きいことはご認識の通りです。PC の買い替えのスピードは企業よりも個人のほうが早く、個人のほうが社内支給デバイスよりも高性能のデバイスを使用しています。このことは業務遂行のストレスとなり、生産性の低下を招きかねません。

    個人デバイスを業務で使用する場合、もっとも心配なのはセキュリティです。個人デバイスは社内支給のデバイスと異なりセキュリティポリシーが適用しづらい難点があります。そのため、多くの企業では個人デバイスの業務利用を禁止せざるをえない状況だと思われます。また、個人デバイスに保存された情報の流出も心配です。

    では、個人デバイスを使用して、安全に業務を遂行させるためのインフラは存在するのでしょうか?

    はい、存在します。

    以下は個人のデバイスを社外から使用することを想定したイメージですが、これは、社内からであっても基本的な考え方は変わりません。

    image1_thumb

    個人のデバイスを使用させる場合に問題となるのは以下の事項です。

    • どうやって社内リソースにアクセスさせるか
    • どうやって個人デバイスのセキュリティに依存しない環境を提供するか
    • どうやって社内で使用しているアプリケーションと同じアプリケーションを使わせるか

    そして、すこし欲張りな要望として以下が挙げられるでしょう。

    • どうやって社内の個人環境を復元するか

    これまで、多くのIT部門が上記に頭を悩ませ、さまざまなルールを作ってきたはずです。中には破綻してしまったルールも少なくないと思います。

    これらのニーズを一気に満たすことができるソリューションが VDI(Virtual Desktop Infrastructure)です。

    VDI ソリューションは各社からリリースされており、いずれを選択するかは現在導入されているインフラストラクチャーとの相性によるでしょう。マイクロソフトが提供する VDI のメリットを最大限に生かすのであれば、Active Directory によるユーザーIDおよびコンピューターの集中管理が必須です。

    VDI ソリューションを使用すると、以下に示すような運用が実現できます。つまり、社内に用意したクライアントOSに、リモートから入り込んで使用することができます。

    image_thumb10

    すでにご想像通り、リモートから社内に入り込む際に使用するのは、リモートデスクトッププロトコル(RDP)です。リモートデスクトップによる接続を有効にしたクライアント OS を社内に用意しておき、社外の PC から RDP クライアントを使用して入り込みます。Windows Server とは異なり、Windows XP や Windows 7 のようなクライアント OS の場合、同時に接続できる リモートデスクトップセッションは 1 つなので、一度に外部から利用するユーザーの数だけクライアントOSを用意しておく必要があります

    リモートデスクトップを使用するメリットは、「セッションの分離」が実現できることです。ユーザーが使用しているクライアントからリモートデスクトップを使用して社内の PC に接続したとしても、両者には明確なセッション境界が存在し、お互いに影響を及ぼしあうことができません。極端な話、利用者の PC が数百のウィルスに感染していたとしても、境界線を越えてリモートデスクトップセッションに入り込むことはできません(もちろん、そのためにはリダイレクト機能を無効にしたり、ネットワーク的な接続経路を遮断しておく必要があります)。

    image_thumb11

    リモートデスクトップセッション内で使用している社内データは、背後から除かれる心配はあるにせよ、そのデータがセッションを超えて社外に流出したり、PC に感染しているウィルスに影響を及ぼされる心配もありません。

    さらに、データ自体は社内にあるので、万が一 PC を紛失してしまってもデータも同時に紛失してしまう...ということもありません。

    さて、ここで多くの方が、以下の一文に何か気持ち悪いものを感じているでしょう。

    「一度に外部から利用するユーザーの数だけクライアントOSを用意しておく必要があります

    安心してください。クライアントOSを用意するとは書きましたが、「PCを用意する」とは書いていません。

    以下はマイクロソフトの VDI ソリューションの模式図です。

    image_thumb1

    上の図にあるように、ポイントは5つです。

    • クライアント OS の仮想化
    • アプリケーションの仮想化
    • ユーザーステータスの仮想化
    • コネクションブローカー
    • 運用管理

    ■ クライアントOSの仮想化

    不特定多数のユーザーが利用するクライアントを物理的に用意する必要はありません。クライアント OS は、Windows Server Hyper-V 上に集約してしまえばよいのです。ユーザーの PC から見て、クライアントOSが仮想化されているかどうかは問題になりません。OS のインストールも通常通り Windows 7 メディアを使用できるので、Hyper-V さえセットアップできれば特に難しいことはありません。

    image_thumb3

    ただし、クライアント OS を仮想化し VDI 環境を提供しようとすると、新たな課題も見えてきます。それらを以下に挙げてみます。

    仮想化されたクライアントの UX
    • 色の再現は(減色されたりしないか)?
    • 解像度は?
    • 音声や動画の再生は可能か?
    • USB デバイスなどを使用できるか?
    • 印刷は可能か?
    個人環境の保存や復元は?
    クライアントの集約率
    • クライアントごとのメモリ確保
    • 仮想クライアントを保存するサーバーのディスクスペース
    仮想クライアント OS の管理
    • 利用者が増減にどう対応できるのか?
    • 無駄な電力を使わないか?
    • 資産管理やサポートはどうするか?

    これらの問題を解消するため、以下のようなテクノロジーや製品が提供されています。

    • RDP 7.1
      最新のリモートデスクトッププロトコル。
      仮想デスクトップ上での Aero を使用した高品質な表示やデバイスのリダイレクト機能などにより、よりローカル PC に近い環境を再現できるようになった。
    • RemoteFX
      サーバーに実装されたGPUを使用して3Dグラフィックスのデコードが可能
      RDP7.1 標準で対応していない USB デバイスを仮想デスクトップにリダイレクト
    • Dynamic Memory
      Hyper-V 上の仮想OSに割り当てるメモリ量を動的に変更できる。初期設定で1024GBと設定されていても、未使用であれば徐々に使用量が減り、たのアクティブな仮想OSに再割り当てされる。
    • Pooled Virtual Desktop
      例えば100人が仮想 OS を利用するとして、100 の仮想クライアントを準備しても、これらが常に使用されるとは限りません。利用率が30%であれば、30台だけ用意しておき、空いているところに自動的に接続するようにできればハードディスクやメモリ、CPUの使用効率を抑えることができます。Pooled Virtual Desktop はそのような機能を提供します。 また、仮想クライアントを停止しておいても、アクセス要求に応じて起動する...と言った設定も可能なので、"微々たるものではありますが"未使用時の電力量を節約することもできます。
    • System Cetner シリーズおよび Windows Intune
      30 の仮想クライアントを準備するには、Widnows 7 Enterprise のインストールを 30 回繰り返す必要があります。あたりまえです。でも、そんなこと受け入れられますか?受け入れられません。そこで登場するのが System Center Virtual Machine Manager です。事前にクライアントOSのテンプレートを作成しておき、必要に応じて仮想マシンを増やしたり、減らしたりすることができます。なんなら、ユーザーからの要求に応じて即時作成したり...と言ったことも可能です。その他の System Center 製品を使用すると、ホストやゲストのパフォーマンスを監視して、別の Hyper-V サーバーにダイナミックにマイグレーションしたり、といったことも可能です。VDI は「幽体化した PC 教室」であると言えます。文教担当のSEさんならばご存知の通り、PC 教室のメンテナンスって結構大変です。それが仮想化されて「ブツ」が見えないとなると、いままでの管理の常識が通用しない場面が多くなります。それをカバーするための運用管理製品も、とても重要なのです。

    長くなってしまったのでこのへんで。

    次回は、3.2 どこからでも接続 ~ 個人のデバイスから社内に接続する② をお送りします

  • 【PowerShell】特定のプロセス起動を監視したいですか?~Register-WMIEvent コマンドレット

    imageぜんぜん話は違うのですが、日本の SQL Server サポートチームの Blog が気合入っています(笑)。今後ともご贔屓にしてくださいませ。評判が悪かったら元に戻すと言っていたので、4月には元に戻っている可能性があります。

    さて、かなり前のことになりますが、以下の資料を SlideShare に投稿しました。このスライドでは、VBScript を使用して、WMI のイベントをリアルタイムに収集するスクリプトについて解説しています。

    image

    このスライドで解説している手法を使用すると、システム内に発生したさまざまなイベントを待ち合わせて、その次のアクションを自動的に実行することができます。

    例えば、次のような処理が簡単に自作できます。

    • 監査ログを監視して、ユーザーが作成されことを検出したらホームディレクトリを自動的に作成する
    • 特定のサービスを監視して、停止したらメールする
    • 特定の誰かがログオンしたらメッセージを表示する
    • 特定のプログラムが起動したら強制的にKILLする

    などなど。

    ※上記スライドには MOF を使用してスクリプトをサービス化する手法についても書かれています

    【PowerShell 1.0 の場合】

    これと同じことが PowerShell でできないだろうか....と思いつつすっかり忘れていましたが、実は初期の PowerShell の頃から同じことは実現可能でした。

    (参考)Windows PowerShell 2.0 - WMI Event Monitoring

    上記の参考リンクでは、以下の様なスクリプトを紹介しています(ちょっとだけ変えています)。このスクリプトでは、WMI の __InstanceCreationEvent というイベント監視用クラスを使用し、Win32_Process を監視しています。クラス名に「Creation」という言葉が入っている通り、「何らかのプロセスが起動したらコンソールにプロセス名を表示する」という動作をします。

    $a = 0 
    $timespan = New-Object System.TimeSpan(0, 0, 1)
    $scope = New-Object System.Management.ManagementScope("\\.\root\cimV2")
    $query = New-Object System.Management.WQLEventQuery `
    ("__InstanceCreationEvent",$timespan, "TargetInstance ISA 'Win32_Process'" )
    $watcher = New-Object System.Management.ManagementEventWatcher($scope,$query)
    do
    {
    $b = $watcher.WaitForNextEvent()
    $b.TargetInstance.Name
    }
    while ($a -ne 1)

    このスクリプトの記載をご覧いただければわかる通り、VBScript とほとんど同じです。Do ~ While でイベントを待ち合わせるのも同じですね。

    もし、「プロセスの停止」を待ち合わせるのであれば、クラス部分を __InstanceDeletionEvent に置き換えます。

    非常に便利なのですが、この書き方だとスクリプトを常駐しておかなければならないという面倒くささがあります。

    【PowerShell 2.0 の場合】

    PowerShell  2.0 では、専用のコマンドレットが提供されました。

    Register-WMIEvent コマンドレットです。

    このコマンドレットにより、上記のスライドに書かれた「スクリプトのサービス化」なんてことをせずとも、WMIイベントを待ち合わせるジョブがシステムに登録されます。

    ※ 以前、田辺さんが紹介されていたのを思い出しました(Windows PowerShell V2 の新機能)。

    そこで、上記のスクリプトを Register-WMIEvent で置き換えると、以下ようなかんじになります。

    少し長いですが、これで1行です。

    Register-WMIEvent -query "Select * From __InstanceCreationEvent within 3 
    Where TargetInstance ISA 'Win32_Process'"

    -sourceIdentifier "NewProcess"
    -Action { $Event.SourceEventArgs.NewEvent.TargetInstance.Name |
    Out-File -FilePath "c:\tmp\log.txt" -Append}
     
    -query の部分は vbscript と変わらないですね。

    上記コマンドレットを実行すると、新しいプロセスが起動するびに、- Action {} 部分が実行されます。

    ここでは起動したプロセスの Name を log.txt というテキストファイルに Out-File しています。

    $Event は、このコマンドレットに組み込みの変数で、WMI のイベントが格納されています。このコマンドレット内でした使用することができません。

    $Event.SourceEventArgs.NewEvent.TargetInstance は、イベント(ここではプロセスの起動)が発生したときに返される Win32_Process のインスタンスです。

    ためしに、以下のように修正して実行し、log.txt の結果を見てみましょう。

    Register-WMIEvent -query "Select * From __InstanceCreationEvent within 3
    Where TargetInstance ISA 'Win32_Process'"

    -sourceIdentifier "testProcess"
    -Action { $Event.SourceEventArgs.NewEvent.TargetInstance | Get-Member |
    Out-File -FilePath "c:\tmp\log.txt" -Append}


    以下のような結果が格納されているはずです。Win32_Process だってことがわかりますね。


    TypeName: System.Management.ManagementBaseObject#root\CIMV2\Win32_Process

    Name MemberType Definition
    ---- ---------- ----------
    AttachDebugger Method System.Management.ManagementBaseObject...
    GetOwner Method System.Management.ManagementBaseObject...
    GetOwnerSid Method System.Management.ManagementBaseObject...
    SetPriority Method System.Management.ManagementBaseObject...
    Terminate Method System.Management.ManagementBaseObject...
    Caption Property System.String Caption {get;set;}
    CommandLine Property System.String CommandLine {get;set;}
    CreationClassName Property System.String CreationClassName {get;s...
    CreationDate Property System.String CreationDate {get;set;}
    CSCreationClassName Property System.String CSCreationClassName {get...
    CSName Property System.String CSName {get;set;}
    Description Property System.String Description {get;set;}
    ExecutablePath Property System.String ExecutablePath {get;set;}
    ExecutionState Property System.UInt16 ExecutionState {get;set;}
    Handle Property System.String Handle {get;set;}
    HandleCount Property System.UInt32 HandleCount {get;set;}
    InstallDate Property System.String InstallDate {get;set;}
    KernelModeTime Property System.UInt64 KernelModeTime {get;set;}
    MaximumWorkingSetSize Property System.UInt32 MaximumWorkingSetSize {g...
    MinimumWorkingSetSize Property System.UInt32 MinimumWorkingSetSize {g...
    Name Property System.String Name {get;set;}
    OSCreationClassName Property System.String OSCreationClassName {get...
    OSName Property System.String OSName {get;set;}
    OtherOperationCount Property System.UInt64 OtherOperationCount {get...
    OtherTransferCount Property System.UInt64 OtherTransferCount {get;...
    PageFaults Property System.UInt32 PageFaults {get;set;}
    PageFileUsage Property System.UInt32 PageFileUsage {get;set;}
    ParentProcessId Property System.UInt32 ParentProcessId {get;set;}
    PeakPageFileUsage Property System.UInt32 PeakPageFileUsage {get;s...
    PeakVirtualSize Property System.UInt64 PeakVirtualSize {get;set;}
    PeakWorkingSetSize Property System.UInt32 PeakWorkingSetSize {get;...
    Priority Property System.UInt32 Priority {get;set;}
    PrivatePageCount Property System.UInt64 PrivatePageCount {get;set;}
    ProcessId Property System.UInt32 ProcessId {get;set;}
    QuotaNonPagedPoolUsage Property System.UInt32 QuotaNonPagedPoolUsage {...
    QuotaPagedPoolUsage Property System.UInt32 QuotaPagedPoolUsage {get...
    QuotaPeakNonPagedPoolUsage Property System.UInt32 QuotaPeakNonPagedPoolUsa...
    QuotaPeakPagedPoolUsage Property System.UInt32 QuotaPeakPagedPoolUsage ...
    ReadOperationCount Property System.UInt64 ReadOperationCount {get;...
    ReadTransferCount Property System.UInt64 ReadTransferCount {get;s...
    SessionId Property System.UInt32 SessionId {get;set;}
    Status Property System.String Status {get;set;}
    TerminationDate Property System.String TerminationDate {get;set;}
    ThreadCount Property System.UInt32 ThreadCount {get;set;}
    UserModeTime Property System.UInt64 UserModeTime {get;set;}
    VirtualSize Property System.UInt64 VirtualSize {get;set;}
    WindowsVersion Property System.String WindowsVersion {get;set;}
    WorkingSetSize Property System.UInt64 WorkingSetSize {get;set;}
    WriteOperationCount Property System.UInt64 WriteOperationCount {get...
    WriteTransferCount Property System.UInt64 WriteTransferCount {get;...
    __CLASS Property System.String __CLASS {get;set;}
    __DERIVATION Property System.String[] __DERIVATION {get;set;}
    __DYNASTY Property System.String __DYNASTY {get;set;}
    __GENUS Property System.Int32 __GENUS {get;set;}
    __NAMESPACE Property System.String __NAMESPACE {get;set;}
    __PATH Property System.String __PATH {get;set;}
    __PROPERTY_COUNT Property System.Int32 __PROPERTY_COUNT {get;set;}
    __RELPATH Property System.String __RELPATH {get;set;}
    __SERVER Property System.String __SERVER {get;set;}
    __SUPERCLASS Property System.String __SUPERCLASS {get;set;}



    ここで注意していただきたいのが –SourceIdentifier パラメタです。-SourceIdentifier には、このジョブの識別名を指定します。ここでは NewProcess と指定しています。
    同じ名前の識別名は指定できないので注意してください。

    登録しておけば、あとは何もせずともずっと監視が続けられます。もちろん、OS を再起動しても消えません。

    監視を終了するには、以下のように Unregister-Event コマンドレットを使用します。

    Unregister-Event NewProcess

    今回は単純な例をご紹介しましたが、もっともっと複雑な処理を実装することもできます。

    それについては今後。

    p.s.

    テストを繰り返していると以下のエラーに見舞われることがあります。そのときは Windows Management Instrumentation サービスを再起動してください。そういう意味では...本番環境ではテストをしないほうがよいです。

    Register-WmiEvent : クォータ違反です
    発生場所 行:1 文字:18
    + Register-WMIEvent <<<< -query
    "Select * From __InstanceCreationEvent within
    3 Where TargetInstance ISA 'Win32_Process'"
    -sourceIdentifier "NewProcess" -Act
    ion { $Event.SourceEventArgs.NewEvent.TargetInstance.Name | Out-File -FilePath
    "c:\tmp\log.txt" -Append}
    + CategoryInfo : NotSpecified: (:) [Register-WmiEvent]、Management
    Exception
    + FullyQualifiedErrorId : System.Management.ManagementException,Microsoft.
    PowerShell.Commands.RegisterWmiEventCommand
     
    これ、解消されていなかったんだなぁ....。
  • 【PowerShell】Hyper-V 系コマンドレットを手元の Windows 7 から実行するには ~ Import-PSSession

    Windows Developer Day 2012 のセッション資料締切も目前なのに、すっかり PowerShell づいています。

    前回、前々回とリモーティングの話を書いてきました。

    リモートにあるサーバーを、手元のクライアントから操作する...などというのが主な使い方になりますが、今後は PowerShell ワークフローをキックしたり、結果を取得したりといった方法にも活用することになります。

    で、リモーティングに関してもう数点ご紹介しておきたい機能があります。

    そのうちの1つが、Import-PSSession というコマンドレットです。

    ご存知ない方も多いのではないかと。このコマンドレットは、PowerShell 2.0 でサポートされました。

    PowerShell ��は Invoke-Command というコマンドレットにより、リモートコンピューターにコマンドを投げることができます。

    ただ、コンソールで対話しているときに Invoke-Command を頻繁に入力するのって疲れるんです。面倒なのです。キーッってなるのです。

    PS C:\> Invoke-Command -ComputerName Server1 -ScriptBlock {Get-VM}

    Enter-PSSession で PSSession に入り込んでもいいのですが、プロンプトが長くなるので、これも キーッ となるのです。

    PS> Enter-PSSession -ComputerName Server1
    [Server1]: PS > Get-VM

    じゃ、手元のマシンに Module をインストールすることができるのか...といえば、出来るものもあるし、できないものもあります。

    RSAT(Remote Server Administration Tool)をインストールすると、Active Directory 関連の PowerShell モジュールはインストールすることができます。

    image

    ちょっと中途半端ですよね。

    そこで、Import-PSSession コマンドレットです。

    image

    Import-PSSession を使用すると、PSSession を張ったリモートコンピューターから、指定したコマンドレットやモジュールをローカルに取り込むことができます。

    以下のように使います。

    はじめにリモートコンピューターとの間に PSSession を作成します。

    PS C:\> $S = New-PSSession -ComputerName Server1 -Name testsession

    次に、Import-Session を使用して、リモートコンピューターから使用したいコマンドレットまたはモジュールを取り込みます。以下の例では、Hyper-V モジュールを指定し、 Hyper-V 系コマンドレットを全てとりこんでいます。

    PS C:\> Import-PSSession -Session $S -Module Hyper-V

    ModuleType Name                                ExportedCommands
    ---------- ----                                ----------------
    Script     tmp_c4aumigk.g4m                    {Add-VMDvdDrive, Add-VMFibreChannelHba, Add-VMHardDiskDrive, Add-VMMi...

    これで Hyper-V モジュールに含まれるすべてのコマンドレットが取り込まれました。

    tmp_c4aumigk.g4m がローカルコンピューターでのモジュール名になるので、こいつを使ってコマンドレットの一覧を見てみると以下の通りです。

    PS C:\> Get-Command -Module tmp_c4aumigk.g4m

    Capability      Name                                               ModuleName
    ----------      ----                                               ----------
    Script          Add-VMDvdDrive                                     tmp_c4aumigk.g4m
    Script          Add-VMFibreChannelHba                              tmp_c4aumigk.g4m
    Script          Add-VMHardDiskDrive                                tmp_c4aumigk.g4m
    Script          Add-VMMigrationNetwork                             tmp_c4aumigk.g4m
    Script          Add-VMNetworkAdapter                               tmp_c4aumigk.g4m
    Script          Add-VMNetworkAdapterAcl                            tmp_c4aumigk.g4m
    Script          Add-VMRemoteFx3dVideoAdapter                       tmp_c4aumigk.g4m
    Script          Add-VMScsiController                               tmp_c4aumigk.g4m
    Script          Add-VMStoragePath                                  tmp_c4aumigk.g4m
    Script          Add-VMSwitch                                       tmp_c4aumigk.g4m
    Script          Add-VMSwitchExtensionPortFeature                   tmp_c4aumigk.g4m
    Script          Add-VMSwitchExtensionSwitchFeature                 tmp_c4aumigk.g4m
    Script          Checkpoint-VM                                      tmp_c4aumigk.g4m


    これで、心置きなく Hyper-V 関連のコマンドレットを使用することができます。

    ただし、注意が2点。

    • コマンドレットはリモートコンピューターとの PSSession 上で実行されます
    • コマンドレットが使えるのは、PSSession が生きている間です。PSSession が切断されるとコマンドレットも消滅しますので注意してください。

    なお、万が一ローカルに同じ名前のコマンドレットが存在する場合には、アラートが表示されて当該コマンドレットは取り込まれません。既存のコマンドレットを一時的に上書きしてでも取り込みたい...といった場合には -DisableNameChecking を指定して Import しましょう。

  • 【Management】PowerShell V3.0 で向上したリモーティング機能 その2

     

    【PowerShell 3.0 で改善されたセッションの永続化機能】

    ※ここからはローカルとリモートの両方が PowerShell 3.0 を使用してることを前提としています。

    前回は、PowerShell 2.0 でのリモーティング機能についてご紹介しました。

    【Management】PowerShell V3.0 で向上したリモーティング機能 その1

    今回は、PowerShell 3.0 によって何が改善されるのかについて解説します。この改善は、ワークフローにとって非常に重要であり、この機能なしにワークフローはありえないと言えるでしょう。

    PowerShell 2.0 と PowerShell 3.0 とではセッション情報の持ち方が変わりました。

    2.0 では New-PSSession を実行したクライアント側にセッション情報が保持されます。そのため、別のクライアントから当該 PSSession を使用することができません。

    image

    一方 PowerShell 3.0 では、セッションの永続性を確保するためにリモートコンピューター側に PSSession を保持します。そのため、PSSession が生きていれば、別のコンピューターから接続して処理を継続したり、ジョブの状態を確認することができるようになりました。

    それに伴い、新しいコマンドレットが追加されています。

    • Connect-PSSession

    事前に New-PSSession でセッションを作成しておくことで、いつでも本コマンドレットで再接続することができます。ただし、別のコンピューターから接続されているセッションに接続することはできません。(-Force オプションが見当たりませんでした)

    • Disconnect-PSSession

    当該コマンドレットを使用すると、接続中のセッションから切断し、セッションの Status を Disconnect にします。Disconnect のセッションには、別のコンピューターから接続することができます。

    • Receive-PSSession

    Disconnect した PSSession からコマンドやジョブの実行結果だけを受け取るためのコマンドレットです。が...私の使い方が悪いのか、現時点ではうまく使えません...。

    では、これらのコマンドレットを使って、ものすごく単純な例で試してみましょう。

    以下のように、3台のマシンがあるとします。いずれも PowerShell 3.0 がインストールされているマシンです。

    image

    【社内PCから】

    社内の PC で、リモートコンピューターに対して新しいセッションを作成します。

    PS C:\> New-PSSession -ComputerName Server1 –Name testSession

    Id Name            ComputerName    State         ConfigurationName     Availability
    -- ----            ------------    -----         -----------------     ------------
    19 testSession     Server1         Opened        Microsoft.PowerShell     Available

    testSession というセッションが作成されました。

    次に、このセッションに接続します。接続するには Connect-PSSession を使用します。このとき、自分で作ったセッションなので -Name でセッション名だけ指定すれば接続できます。

    PS C:\> Connect-PSSession -Name testSession

    Id Name            ComputerName    State         ConfigurationName     Availability
    -- ----            ------------    -----         -----------------     ------------
    19 testSession     Server1         Opened        Microsoft.PowerShell     Available

    さらに、このセッションに Enter-PSSesssion で入り込みましょう。

    そして、セッションの継続性を確認するために、$a という変数を作り、セッションから抜け出します。

    PS C:\> Enter-PSSession -Name testSession
    [server1]: PS C:\> $a = 1
    PS C:\> Exit-PSSession

    この状態ではまだセッションに Connect された状態なので、他のコンピューターから接続しようとしてもエラーが発生します。

    なので、セッションを Disconnect します。とても重要です。

    PS C:\> Disconnect-PSSession -Name testSession

    Id Name            ComputerName    State          ConfigurationName     Availability
    -- ----            ------------    -----          -----------------     ------------
    19 testSession     Server1         Disconnected  Microsoft.PowerShell          None

    以上で完了です。

    【自宅のPCから】

    今度は別のコンピューターに移動します。ここでは「自宅のPC」と仮定しています。

    はじめに、サーバー Server1 のセッション状態を確認してみます。State が Disconnect になっていることがわかります。

    PS C:\> Get-PSSession –ComputerName Server1

    Id Name            ComputerName    State         ConfigurationName     Availability
    -- ----            ------------    -----         -----------------     ------------
    19 testSession     Server1         Disconnected 
    http://schemas.mi...          None

    ここに Connect-PSSession しましょう。Disconnected が Opened になったことがわかります。

    PS C:\> Connect-PSSession -Name testsession -ComputerName Server1

    Id Name            ComputerName    State         ConfigurationName     Availability
    -- ----            ------------    -----         -----------------     ------------
    27 testSession     Server1         Opened       
    http://schemas.mi...     Available

    次に Enter-PSSession して、$A の中身を確認してみます。

    PS C:\> Enter-PSSession -name testsession
    [junichia-vdi]: PS C:\> $A
    1
    [junichia-vdi]: PS C:\>Exit-PSSession

    いかがでしょう?非常に単純な例で恐縮なのですが、セッションに再接続できることがご理解いただけたかと思います。

    セッションを使い終わったら、かならず Remove-PSSession でセッションを削除しておきましょう。

  • 【Management】PowerShell V3.0 で向上したリモーティング機能 その1

    現行の Windows PowerShell 2.0 では、「リモーティング」と呼ばれる機能がサポートされています。リモーティングとは、「リモートコンピュータに対する操作」のことです。

    運用管理を自動化するにはリモーティングは欠かせない機能ですので、PowerShell ユーザーの方はぜひ押さえておきましょう。

    【PowerShell 2.0 でサポートされているリモーティング】

    PowerShell のリモーティングの使い方は、大きく 4 種類に分かれます。

    • コマンドレットの –ComputerName パラメタを使用する

    (例)Get-Service -ComputerName Server01

    ただし、全てのコマンドに –ComputerName が実装されているわけではないので、以下に示すような方法を使用する必要があります。

    • Enter-PSSession / Exit-PSSession

    telnet や ssh のようにリモートコンピュータとセッションを構築し、その中でコマンドレットを実行することができます。セッションの有効期間は、Enter-PSSession 実行から Exit-PSSession 実行までです。

    PS> Enter-PSSession -ComputerName Server1
    [Server1]: PS > $A = 1
    [Server1]: PS > $B = 2
    [Server1]: PS > $C = $A + $B
    [Server1]: PS > 3
    PS> Exit-PSSession

    • Invoke-Command

    以下のように Invoke-Command を使用すると、-ComputerName で指定したコンピュータに対してコマンドレットを投げ、その結果だけを受け取ります。セッションはその都度消滅するので、例えば上の例のように、$C = $A + $B の計算結果が 3 にはなりません。なぜならば、セッションが消滅してしまうので、セッション中の変数も消滅してしまうからです。

    PS C:\> Invoke-Command -ComputerName junichia-vdi -ScriptBlock {$A = 1}
    PS C:\> Invoke-Command -ComputerName junichia-vdi -ScriptBlock {$B = 2}
    PS C:\> Invoke-Command -ComputerName junichia-vdi -ScriptBlock {$C = $A + $B}
    • 永続化されたセッションを使用する

    セッションを永続化するには、New-PSSession コマンドレットを使用します。以下の例では、Server1 との間に TestSession という名前のセッションを作成しています。作成したセッションに入り込むには、Enter-PSSession に –Name <セッション名> を指定します。Invoke-Command でも セッション名を指定してコマンドを送信することができます。

    PS C:\> New-PSSession -ComputerName Server1 -Name TestSession
    PS C:\> Enter-PSSession -Name TestSession
    [Server1]: PS C:\> $A = 1
    [Server1]: PS C:\> $B = 2
    [Server1]: PS C:\> $C = $A + $B
    [Server1]: PS C:\> $C
    3
    [Server1]: PS C:\> Exit-PSSession
    PS C:\>

    作成したセッションは、削除しなければそのまま残ります。現在保持しているセッションの一覧を取得するには、Get-PSSession を使用します。

    PS C:\> Get-PSSession

    Id Name            ComputerName    State    ConfigurationName     Availability
    -- ----            ------------    -----    -----------------     ------------
      1 TestSession    Server1         Opened   Microsoft.PowerShell     Available

    保持しているセッションはローカルコンピューターが再起動されない限り永続化されるので、再度 Enter-PSSession を使用して接続することができます。

    ただし、作成したセッションを別のクライアントから使用することはできません。これは、PowerShell 2.0 ではセッション情報がローカルコンピューターに保持されるためです。

    また、ローカルコンピューターを再起動してしまうと、作成したセッションは消滅してしまいます。

    さらに、リモートコンピュータが再起動されるとセッションは破壊され、接続することができなくなります。

    PS C:\> Get-PSSession -ComputerName Server1

    Id Name         ComputerName State   ConfigurationName    Availability
    -- -----------  ------------ -----   -----------------    ------------
    TestSession Server1      Broken Microsoft.PowerShell None

    PS C:\> Enter-PSSession -Name TestSession

    Enter-PSSession : セッションが開かれている必要があります。
    発生場所 行:1 文字:16
    + Enter-PSSession <<<< -Name tmpsession
    + CategoryInfo : InvalidArgument: (:) [Enter-PSSession]、ArgumentException
    + FullyQualifiedErrorId : PushedRunspaceMustBeOpen,Microsoft.PowerShell.Commands.EnterPSSessionCommand

    ちなみに、セッションの利用が完了したら、Remove-PSSession でセッションを削除することができます。
    PS C:\>Remove-PSSession -Name TestSession

    次の投稿で、PowerShell 3.0 で改善されたセッション永続化について解説します。

    つづき 【Management】PowerShell V3.0 で向上したリモーティング機能 その2