PowerShell v5 正式リリース (PowerShell DSC実践活用・特別編)
PowerShell v5の新機能と、実戦で使ってほしい機能
Windows 10に標準搭載され、Windows 7/8.1/Server 2008/2012向けにもリリースされたWMF 5.0に同梱されるPowerShell 5.0の新機能と、PowerShellユーザーに特にお勧めの機能を紹介する。
2015年12月16日、PowerShell 5.0を含むWindows Management Framework 5.0 RTM(以下、WMF 5.0 RTM)がリリースされたが、PSmodulePath
に問題があったため12月23日にいったん回収され、公開が取り消されていた。2016年2月25日にようやくその問題が修正され、再度、WMF 5.0 RTMがリリースされたことで本番環境におけるWMF 5.0の利用が全面解禁された。
本連載では、「Windows Management Framework」のバージョン4.0(WMF 4.0)を基盤にPowerShell DSCを実践で使うための手法を紹介してきた。PowerShell 5.0からはDSC周りの機能が大幅に強化されているが、それ以外にも多くの更新がある。
そこで今回は、「PowerShell 5.0の新機能全体の概要」と「(インフラエンジニアをはじめとして多くの人に)実戦で使ってほしい機能」について紹介しよう。
PowerShellに関するフィードバック
本連載の後、PowerShell 5.0を触っていて、改善してほしいことに気付いたら、ぜひフィードバックしてほしい。フィードバック方法は、従来のMicrosoft Connect : PowerShellから、他プロダクトでも広く使われているUserVoiceに移行しており、より一層の改善を図る姿勢だ。
WMF 5.0のインストール
まずは、WMF 5.0 RTMがサポートしている環境だ。
Operating System | サービスパック | エディション | 前提条件 |
---|---|---|---|
Windows Server 2012 R2 | IA64(Itanium)を除く全て | .NET 4.5以上 | |
Windows Server 2012 | IA64(Itanium)を除く全て | .NET 4.5以上 | |
Windows Server 2008 R2 | SP1 | IA64(Itanium)を除く全て | WMF 4.0の事前インストール/.NET 4.5以上 |
Windows 8.1 | Pro、Enterprise | ||
Windows 7 | SP1 | 全て | WMF 4.0の事前インストール/.NET 4.5以上 |
※Windows 10には最初からWMF 5.0が搭載されている。
以下のアプリケーションがインストールされている環境にはWMF 5.0はインストールできないのでお気を付け願いたい。
- Microsoft Exchange Server 2013
- Microsoft Exchange Server 2010 SP3
- Microsoft SharePoint Server 2013
- Microsoft SharePoint Server 2010
- System Center 2012 Virtual Machine Manager
※これまで、System Center 2012 Configuration Managerをインストール済みの環境にはWMF 5.0のインストールができなかったが、RTMからはインストール可能になった。
インストールは簡単だ。
上記リンク先のダウンロードサイトからインストーラー(.msuファイル)を環境に合わせてダウンロードしたら(表2を参照)、その.msuファイルを実行するだけだ。
Operating System | アーキテクチャ | インストールパッケージ名 |
---|---|---|
Windows Server 2012 R2 | x64 | Win8.1AndW2K12R2-KB3134758-x64.msu |
Windows Server 2012 | x64 | W2K12-KB3134759-x64.msu |
Windows Server 2008 R2 | x64 | Win7AndW2K8R2-KB3134760-x64.msu |
Windows 8.1 | x64 | Win8.1AndW2K12R2-KB3134758-x64.msu |
Windows 8.1 | x86 | Win8.1-KB3134758-x86.msu |
Windows 7 SP1 | x64 | Win7AndW2K8R2-KB3134760-x64.msu |
Windows 7 SP1 | x86 | Win7-KB3134760-x86.msu |
本記事では、Windows Server 2012 R2 x64にWMF 5.0 RTMをインストールした例と、Windows 10 TH2(Threshold 2)で実行した例を交えて紹介する。
PowerShell 5.0で追加された新機能一覧
まずはリリースノートから全体像を示そう。
上記リンク先のリリースノートに書かれたPowerShell 5.0の機能一覧を、筆者が大きく6項目に分類したのが表3だ(※本稿では「コマンドレット」は英語表記のまま「Cmdlet」もしくは「Cmdlets」と記載する)。
※この表では、同じ機能が複数の分類で利用可能な場合は、どこか一つの分類に統合している。
各機能の詳細はリンク先を参照してほしい。本稿の本文内で説明されている機能はその該当箇所にジャンプし、それ以外は公式の説明ページ(英語)を開く。
PowerShell 4.0の目玉はPowerShell DSC(Desired State Configuration)のリリースだった。PowerShell 5.0では、従来のPowerShell DSC以外にも新旧Cmdletの強化、ソフトウェアデリバリー以外にもクラス構文を導入した。これまでPowerShellは、IT Proを中心に利用シーンを想定していたが、PowerShell 5.0は開発者にとっても利用しやすくすることも視野に入れた強化といえる。
それでは、分類した各項目の概要と、実戦で使ってほしい機能を紹介しよう。
セキュリティと監査
これまでのPowerShellは、Windowsのシステム操作に関しては極めて強力だが、操作に関する追跡や制約は不十分だった。そこでPowerShell 5.0では、セキュリティ監査機能の強化が2つの視点で行われた。それが、「管理権限で実行できる操作と範囲自体の制限」と「ロギングの強化」だ。
管理権限で実行できる操作と範囲自体の制限
Just Enough Administration(JEA)として、この機能が追加されている。従来のユーザーアカウント制御(UAC)では、管理者への昇格を制限できていたが、管理者権限で実行できる操作や範囲の制御はできなかった。JEAを使うことで、管理者がユーザーに管理者権限を要する操作環境を提供する際に、PowerShellホストで行える操作/範囲を制限可能になった。AzureのRoll Base Account Control(RBAC)やAWSのIAM Roleに近いイメージを持つと分かりやすいだろう。
ロギングの強化
Power WormなどのPowerShellを使ったマルウェアの登場を受けて、イベントログなどへの自動的なロギング(Script Tracing)と、そのログの暗号化(CMS(Cryptographic Message Syntax) Cmdlets)に関する機能が追加された。これにより管理者は、PowerShellによって操作された内容を、イベントログを通して把握できるようになった。また、攻撃者がイベントログからPowerShell操作を読み取って悪用しようとしても、暗号化してあるため防ぐことができるのだ。
管理者にとって自動ロギングと暗号化による追跡可能性の向上はうれしい機能だろう。
Transcription
特に使ってほしい便利な機能が、Start-Transcription
Cmdletの強化(Transcription)だ。これまではPowerShell.exe(=コンソール)でしか実行できなかった同Cmdletが、PowerShell ISEなどホスト環境を選ばず実行してロギング可能になっている。PowerShellの操作やスクリプトを利用しているだけで、コード例1/図1のように自動的にロギングされるので、非常に簡単だ。Transcriptionをぜひ活用してほしい。
Start-Transcript -OutputDirectory c:\transcription
Get-Date
cat c:\transcription\PowerShell_transcript.WINDOW10PRO.GomwfWtu.20151225023325.txt
|
※最後の行のファイル名は環境によって異なるので、環境に合わせて変えてほしい。
これらのセキュリティと監査に関する詳細は、別途、PowerShell Teamからのブログアナウンスがあるのでご覧いただきたい。
開発
WMF 4.0までのPowerShellは、数行~数十行程度の処理なら書きやすいが、1人の開発者として考えたとき、ある程度の規模以上のスクリプトを組みやすいとは言いにくいものがあるように感じる。PowerShell 5.0では、開発面においても「デバッグ機能」「リモートファイル編集」「クラス構文」の3つの側面で強化されている。
デバッグ機能の強化
まずは開発過程で欠かすことができないデバッグ機能の強化だ。「PowerShell.exeとPowerShell ISEで実行中のスクリプトのデバッグブレーク」や「ランスペース・デバッグ*1」、「リモートPowerShellプロセスデバッグ」がCmdlet一つで可能になったことで(表4)、開発効率が大きく向上したことが実感できるだろう。
- *1 「ランスペース」とはプロセス内のPowerShell実行インスタンスのことで、英語では「Runspace」と記載し、日本語では「実行空間」とも呼ばれる。今回の機能強化では、その実行空間にPowerShell.exeやPowerShell ISEをアタッチして、PowerShellスクリプトをデバッグできるようになった。
デバッグ操作 | 追加されたCmdlet |
---|---|
リモートPowerShellプロセスのデバッグCmdlet | Get-Runspace Debug-Runspace Enable-RunspaceDebug Disable-RunspaceDebug Get-RunspaceDebug |
リモートプロセスのデバッグCmdlet | Enter-PSHostProcess Exit-PSHostProcess |
リモートホストにあるファイルの直接編集
LinuxやUNIXなどの非Windows環境では、SSHでリモートシェルにつないでエディターを立ち上げてファイルを直接編集できるが、これがPowerShellでも同様にリモートセッション先にあるファイルの編集ができるようになった。
試すには、PowerShell ISEでEnter-PSSession
Cmdletを使ってリモートホストにつないでいる最中にPSEdit "対象ホストのパス"
と入力してほしい。図2のように、[Remote File] <ファイル名>
タブが新規にできて直接ファイルを編集できることが確認できる。
これまでファイルの中身を編集するだけのためにリモートデスクトップでつないでいたようなシーンは、この機能をもって置き換えることができるだろう。
クラス構文の追加
クラス構文によって、他のオブジェクト指向プログラミング(OOP)言語と同じようなシンタックスやセマンティックスが提供された。クラス構文では、レキシカルスコープ、ユーザー定義型の定義、クラスの継承、例外のハンドリングなどが実装されたことで、これまでC#などのOOP言語を触ってきた方にとっては関数よりも意図した通りに書きやすくなるだろう。
簡単なC#サンプルとクラス構文を比較しつつ、構文を紹介していく*2。C#のサンプルは、Build Insiderでオピニオンもかかれている岩永氏のC#解説サイトから本人の許可を得て拝借した。
- *2 余談だが、開発最初期のクラス構文はRubyに近いもので変数の宣言などは
def
だった。2014年10月にお目見えしてからは、現在同様のC#に近い構文を意識して作られており、今後もC#に近い構文が期待できるだろう。
クラス構文と継承
さて、PowerShellで関数を宣言する際はfunction
キーワードを用いていたが、クラスを宣言するにはclass
キーワードを使う。継承する場合は、派生クラス : 基底クラス
だ。簡単なクラスを見てみよう。コード例2では、比較して理解できるように、C#のコード例も併記している。
void Main()
{
var student = new Student();
}
class Person
{
public string Name { get; set; }
public int Age { get; set; }
public Person()
{
Console.WriteLine("Base constructor called");
}
}
class Student : Person
{
public int Id { get; set; }
public Student()
{
Console.WriteLine("Derived constructor called");
}
}
|
function Main()
{
# クラスのインスタンスを生成するときは[型]::New()メソッドを利用する。
# 従来のNew-Object "Student"; による文字ベースでの型指定は利用できない
$student = [Student]::New();
}
# 基底クラス
class Person
{
[string]$Name; # 型が指定されないと[object]扱い
[int]$Age; # ; か改行を終端に用いる
# コンストラクター
Person()
{
Write-Host "Base constructor called";
}
}
# class 派生クラス : 基底クラス で継承する
class Student : Person
{
[int]$Id;
Student()
{
Write-Host "Derived constructor called";
}
}
|
両方ともMain
メソッドを実行すると同じメッセージがコンソールに出力され、継承元クラスが初期化されてから継承先クラスが初期化されたことが分かる。
Base constructor called
Derived constructor called
|
ちなみにコード例3のように.NET Frameworkの型も継承できる。恐らくusing namespace <名前空間名>
というキーワードが見慣れない方も多いだろう。リリースノートに記載がないものの、PowerShell 5.0から追加されたこのキーワードと共に必要な名前空間をスクリプト先頭に記述すれば、スクリプト本文では名前空間を省略して記述できるようになった(機能としてはC#でいうusing
ディレクティブと全く一緒)。
using namespace System.Collections.Generic;
# .NET Frameworkの型を継承する例
class MyIntList : List[int]
{
}
$list = [MyIntList]::New()
$list.Add(100)
$list[0] # return 100
|
インターフェースの実装
同様にインターフェースの実装も可能だ。これもC#同様の構文であることが分かっていただけるだろう(コード例4)。
void Main()
{
var sw = new Stopwatch();
sw.Dispose();
}
class Stopwatch : IDisposable
{
System.Diagnostics.Stopwatch _s = new System.Diagnostics.Stopwatch();
public Stopwatch() { _s.Start(); }
public void Dispose()
{
_s.Stop();
Console.WriteLine(_s.Elapsed);
}
}
|
function Main()
{
$sw = [Stopwatch]::New();
$sw.Dispose();
}
class Stopwatch : IDisposable
{
[System.Diagnostics.Stopwatch] $_s = [System.Diagnostics.Stopwatch]::new();
Stopwatch () { $this._s.Start(); }
[void] Dispose()
{
$this._s.Stop();
[Console]::WriteLine($this._s.Elapsed);
}
}
|
両方ともMain
メソッドを実行すると、Stopwatch.Elapsed
プロパティの値がコンソールに出力される。
00:00:00.0001101
|
当然だが、インターフェースで定義されたDispose()
メソッドを実装しないとエラーが表示される(コード例5)。
function Main()
{
$sw = [Stopwatch]::New();
$sw.Dispose();
}
class Stopwatch : IDisposable
{
[System.Diagnostics.Stopwatch] $_s = [System.Diagnostics.Stopwatch]::new();
Stopwatch () { $this._s.Start(); }
}
|
発生場所 行:7 文字:1
+ class Stopwatch : IDisposable
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
型 "Stopwatch" の作成中にエラーが発生しました。エラー メッセージ:
アセンブリ '⧹powershell, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' からの型 'Stopwatch' にあるメソッド 'Dispose' に実装が含まれていません。
+ CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : TypeCreationError
|
多段継承と、実装の隠ぺい
クラス構文では多段継承も可能だ。一方でC#同様に多重継承はサポートしていない。
ただし注意が必要なのが、PowerShellの全クラスメンバーはモジュールやスクリプトのスコープにおいてはアクセス修飾子がpublic
であるということだ。現時点では、C#で行うようなprivate
/protected
/internal
アクセス修飾子による実装の隠ぺいがクラス構文ではできない(コード例6)。
// C#での実装のカプセル化例
void Main()
{
var faker = new Seventeen("Jane Does", 28, 1);
faker.Age = 17; // 意図した通り、プロパティの書き替えができずコンパイルエラーとなる
}
class Person
{
public string Name { get; private set; }
public int Age { get; private set; }
public Person(string name, int age)
{
this.Name = name;
this.Age = age;
}
}
class Student : Person
{
public int Id { get; private set; }
public Student(string name, int age, int id) : base(name, age)
{
this.Id = id;
}
}
class Seventeen : Student
{
public bool IsReal
{
get
{
return this.Age == 17 ? true : false;
}
}
public Seventeen(string name, int age, int id) : base(name, age, id)
{
}
}
|
# PowerShellクラスでは実装をカプセル化できない
function Main()
{
$faker = [Seventeen]::New("Jane Does", 28, 1);
$faker.Age = 17; # 書き替えができてしまう
}
class Person
{
[string]$Name; # フィールドはPublic扱いで、PrivateやReadOnlyにはできない
[int]$Age;
Person([string]$name, [int]$age)
{
$this.Name = $name;
$this.Age = $age;
}
}
# クラスの継承
class Student : Person
{
[int]$Id;
# 基底クラスのコンストラクター呼び出し
Student([string]$name, [int]$age, [int]$id) : base($name, $age)
{
$this.Id = $id;
}
}
# 多段継承
class Seventeen : Student
{
[bool]$IsReal; # Get Onlyプロパティの設定や、Privateアクセス修飾子がない
Seventeen([string]$name, [int]$age, [int]$id) : base($name, $age, $id)
{
# Get Onlyプロパティの代わりにコンストラクターで設定する
$this.IsReal = if ($this.Age -eq 17)
{
$true
}
else
{
$false
}
}
}
. Main
|
クラス構文には、フィールドやメソッドをIntelliSenseやGet-Member
での出力から隠すことができるHidden
キーワードがある。ただし、コード例7のようにGet-Memeber -Force
で見ることができることに加えて、Setが可能だ。そのためprivate
アクセス修飾子のような使い方はできず、IntelliSenseから隠す程度の効果しかないことに注意してほしい。
# HiddenキーワードによるIntelliSenseからの隠ぺい例
class Person
{
[string]$Name; # フィールドはPublic扱いで、Private化はできない
[int]$Age;
Hidden [string]$hidden = "initial"; # Hiddenキーワードをプロパティに付与した例
Person([string]$name, [int]$age)
{
$this.Name = $name;
$this.Age = $age;
}
# Helloメソッド
# [返戻値の型]メソッド名(引数)で定義する
[void]Hello()
{
[Console]::WriteLine("Hello $($this.Name).")
}
# Hiddenキーワードはメソッドにも付与できる
Hidden [void]SetHidden([string]$text)
{
$this.hidden = $text;
}
}
$person = [Person]::New("Hoge", 1);
$person.hidden # IntelliSenseには出ないが、初期値のinitialが出力される
$person | Get-Member # Hiddenキーワードの変数やメソッドは出力されない
$person | Get-Member -Force # -Forceスイッチを付けるとHiddenキーワードを付けていても出力される
$person.SetHidden("text") # hiddenプロパティに文字列を設定するメソッドが呼び出せる
$person.hidden # SetHidden()メソッドで設定したtextが出力される
|
列挙型(enum)
クラス構文によって、enum
キーワードを用いて列挙型を簡単に作成できるようになった。PowerShell 4.0までは、文字ベースでC#のenum
構文を書いてAdd-Type
で読み込む必要があったので、かなり便利に感じるだろう(コード例8)。
# PowerShell4.0までの列挙型はC#文字列の動的コンパイルだった
Add-Type @'
public enum Colours
{
Red,
Blue,
Green,
}
'@
[Colours]::Red; # Red が出力される
|
# クラス構文での列挙型は、enumキーワードを用いる
enum Colours
{
Red
Blue
Green
}
[Colours]::Red; # Redが出力される
|
コンストラクターのオーバーロード一覧
クラス構文のコンストラクターのオーバーロード一覧は、IntelliSenseで表示される他にも[<型名>] | Get-Member -Static
でnew
メソッドの定義として出力できる(図3参照)。
コード例6を実行した後の状態で、[Student] | Get-Member -Static
というコマンドを実行したところ。
出力された一覧における[Name]列がnew
のものがコンストラクター・オーバーロードとなる。
その他の機能
DSCリソースの記述においては、クラス構文用の属性(DscResource
/DscResourceKey
/DscResourceMandatory
/DscResourceOut
)もサポートされているため、関数に比べて圧倒的に制御しやすくなると実感している。開発者に限らず、PowerShellである程度の規模のモジュールやスクリプトを書くときには候補にしてほしいと思う。
コード例には挙げなかったが、namespace
やstatic
フィールド、static
コンストラクター、static
メソッドも持つことができる。
最後に現在のクラス構文には他にも以下のような制約がある。
- 同一クラスの異なるシグネチャのコンストラクターを呼び出すこと(C#の
: this()
相当)はできないため、初期化メソッドを利用するなどの回避が必要 - クラス構文で定義した型は、モジュールやスクリプトファイルの外からは参照できない
いかがだろうか、開発者にとってはこれまでの関数を用いた記述よりも馴染みやすい構文と感じていただけたのではないだろうか。PowerShellのオブジェクトはパイプライン|
を使って次に渡していくスタイルなので、パイプラインで型が定義できることで、その利便性が上がったという印象もある。現時点の筆者の触り心地からすると、完全なOOP的な振る舞いで書いていくよりは、生データを触るのに近い印象だ。
DSC
PowerShell 5.0で最も恩恵を受けるのはPowerShell DSCだ。他の機能に比べて数多くの更新が入ったため、特に利用してほしい機能を抜粋して紹介する。より詳しくはリリースノートを参照してほしい。なお、本節のDSCに関する新機能を理解するには、本連載「PowerShell DSC実践活用」で説明してきた基礎知識が必要となるので、必要に応じて適宜、読み返してほしい。
ノード間の協調動作
ノード間の協調動作が可能になったことで、「役割の異なるノードそれぞれの動作を制御して構成する」ことも容易になった。コード例9は「ノードAをADDS(Active Directory Domain Services)に参加させたい」という内容をConfigurationで表現したものだ。この例では、WaitForAll
リソースとDependsOn
プロパティにより、ノードBのADDS構成が完了するまでノードAの処理が待機し、ノードBのADDSが準備できたらノードAがドメインに参加する、という一連の構成処理が自動化されている。
Configuration JoinDomain
{
Import-DscResource -Module xComputerManagement
WaitForAll DC
{
ResourceName = '[xADDomain]NewDomain'
NodeName = 'NodeB'
RetryIntervalSec = 15
RetryCount = 30
}
xComputer JoinDomain
{
Name = 'NodeA'
DomainName = 'Contoso.com'
Credential = (get-credential)
DependsOn = '[WaitForAll]DC'
}
}
|
なお、DSCリソースとしてインポートしている「xComputerManagement」モジュールは、PowerShell DSC Resource Kitの一部で、PowerShell Galleryからインストールできる。Get-credential
Cmdletは、ユーザー名とパスワードをダイアログボックス上でユーザーに入力してもらい、それを基にユーザークレデンシャル(=ユーザー証明情報)オブジェクトを作成するためのもの。詳しくはこちらを参照してほしい。
「Get-DscConfigurationStatusの追加」と「Test-DscConfigurationの強化」
これらは筆者が最もうれしいと実感しているDSCの機能強化だ。現在、PowerShell DSCを使っている人にとっても最もうれしい更新だろう。
前回の記事「本番で使えるPowerShell DSCリソース作成入門」においてTest-DscConfiguration
Cmdletを紹介したが、PowerShell 4.0においてはbool値の結果しか返ってこなかった。これはつまり、ノードに適用した全Configurationが通ればtrue、1つでも失敗すればfalseを意味するものの、「どのConfigurationが成功、もしくは失敗したのかを判別」する機能までは提供してくれていなかったことを意味する。1つのConfigurationならいいが、2つ以上になると切り分けにはサーバーの状態をテストするしかなく大変な労力を伴う。DSCの一番の要であるテスト機能が貧弱だったのは、まぎれもない事実だった。
しかしPowerShell 5.0では、Get-DscConfigurationStatus
Cmdletの追加やTest-DscConfiguration
Cmdletの強化によって、「適用されたConfigurationから成功/失敗したConfigurationが個別に把握可能」になった。コード例10は、d:\fuga
とx:\fuga
にフォルダーを作るConfigurationだが、適用するノードにはX:ドライブがないため[File]Fuga
Configurationは必ず失敗すると思ってほしい。
Configuration Hoge
{
Import-DscResource -ModuleName PSDesiredStateConfiguration
Node 127.0.0.1
{
File Hoge
{
Ensure = 'Present'
DestinationPath = "d:\fuga"
Type = "Directory"
Force = $true
}
File Fuga
{
Ensure = 'Present'
DestinationPath = "x:\fuga"
Type = "Directory"
Force = $true
}
}
}
Hoge -OutputPath d:\hoge;
$session = (New-CimSession -ComputerName 127.0.0.1);
Start-DscConfiguration -Path d:\hoge -Wait -Force -Verbose -CimSession $session;
|
Get-DscConfigurationStatusコマンドレット
Configuration適用後に、Get-DscConfigurationStatus
Cmdletを実行した結果がコード例11だ。ResourcesInDesiredState
に成功したConfiguration、ResourcesNotInDesiredState
に失敗したConfigurationが明示されている。
PS> Get-DscConfigurationStatus
DurationInSeconds : 0
Error : The SendConfigurationApply function did not succeed.
HostName : WINDOW10PRO
IPV4Addresses : {169.254.54.128, 169.254.145.119, 169.254.40.31, 192.168.11.111...}
IPV6Addresses : {fe80::2c05:b3b:8fb:281f%9, ::2000:0:0:0, ::1, ::2000:0:0:0...}
JobID : {4902A626-A5C8-11E5-9BDD-E0CB4EA477F0}
LCMVersion : 2.0
Locale : ja-JP
MACAddresses : {E0-CB-4E-A4-71-CD, E0-CB-4E-A4-77-F0, 10-66-82-18-4D-F6, 10-66-82-18-4D-F6...}
MetaConfiguration : MSFT_DSCMetaConfiguration
MetaData : Author: admin; Name: Hoge; Version: 2.0.0;
GenerationDate: 12/19/2015 05:45:35; GenerationHost:
WINDOW10PRO;
Mode : PUSH
NumberOfResources : 2
RebootRequested : False
ResourcesInDesiredState : {[File]Hoge}
ResourcesNotInDesiredState : {[File]Fuga}
StartDate : 12/19/2015 5:45:35 AM
Status : Failure
Type : Initial
PSComputerName : 127.0.0.1
CimClass : root/Microsoft/Windows/DesiredStateConfiguration:MSFT_DSCConfigurationStatus
CimInstanceProperties : {DurationInSeconds, Error, HostName, IPV4Addresses...}
CimSystemProperties : Microsoft.Management.Infrastructure.CimSystemProperties
|
さらに、コード例12に示すように、Configurationが失敗した理由まで掘り下げることができるため、Get-DscConfigurationStatus
Cmdletは本当に重宝するだろう。
PS> $status = Get-DscConfigurationStatus
PS> $status.ResourcesNotInDesiredState
ConfigurationName : Hoge
DependsOn :
ModuleName : PSDesiredStateConfiguration
ModuleVersion : 1.1
PsDscRunAsCredential :
ResourceId : [File]Fuga
SourceInfo : ::14::9::File
DurationInSeconds : 0.027
Error : The system cannot find the path specified. The related
file/directory is: x:\fuga. The related ResourceID is
[File]Fuga.
FinalState :
InDesiredState : False
InitialState :
InstanceName : Fuga
RebootRequested : False
ResourceName : File
StartDate : 12/19/2015 5:45:35 AM
PSComputerName : 127.0.0.1
|
[File]Fuga
Configurationの失敗詳細の表示Test-DscConfigurationコマンドレット
成功/失敗を確認できるTest-DscConfiguration
Cmdletでも、従来のbool値(true/false)以上の詳細情報が取得できる(コード例13)。
PS> Test-DscConfiguration -Path d:\hoge -CimSession $session
InDesiredState : False
ResourcesInDesiredState : {[File]Hoge}
ResourcesNotInDesiredState : {[File]Fuga}
ReturnValue : 0
PSComputerName : 127.0.0.1
|
もちろん、コード例14に示すように、Get-DscConfigurationStatus
と同様の「失敗したConfigurationの詳細」が見られる。
PS> $status = Test-DscConfiguration -Path d:\hoge -CimSession $session
PS> $status.ResourcesNotInDesiredState
ConfigurationName : Hoge
DependsOn :
ModuleName : PSDesiredStateConfiguration
ModuleVersion : 1.1
PsDscRunAsCredential :
ResourceId : [File]Fuga
SourceInfo : ::14::9::File
DurationInSeconds : 0.012
Error :
FinalState :
InDesiredState : False
InitialState :
InstanceName : Fuga
RebootRequested : False
ResourceName : File
StartDate : 12/19/2015 5:56:20 AM
PSComputerName : 127.0.0.1
|
[File]Fuga
Configurationの失敗詳細の表示 Test-DscConfiguration
Cmdletは、指定したMOF(Managed Object Format)ドキュメントをノードに適用せずに(つまりConfigurationを実際には実施せずに)テストすることも可能になった(コード例15)。これにより、繰り返しのテスト作業がはるかに簡便に行えるようになるので、PowerShell DSCの使い勝手は大幅に増すだろう。
Test-DscConfiguration -ReferenceConfiguration D:\hoge\127.0.0.1.mof -CimSession $session
|
任意のDSC実行ユーザー
PowerShell 4.0までは、DSCの実行ユーザーがBuiltIn/SYSTEMユーザーに固定されていたため、別ユーザーのコンテキストで実行したいときはタスクスケジューラーを使うなど迂回措置を取る必要があった。
PowerShell 5.0では、任意のユーザークレデンシャルでConfigurationを適用できるようになった。前掲のコード例9で見たDependsOn
プロパティと同様に、PsDscRunAsCredential
プロパティを各Configurationに追加できるようになったことで、必要に応じて意図した任意のユーザーコンテキストで各Configurationを適用できる(コード例16)。
Configuration ChangeCmdBackGroundColor
{
Node ("localhost")
{
Registry CmdPath
{
Key = "HKEY\_CURRENT\_USER\\\\Software\\Microsoft\\\\Command Processor"
ValueName = "DefaultColor"
ValueData = '1F'
ValueType = "DWORD"
Ensure = "Present"
Force = $true
Hex = $true
PsDscRunAsCredential = get-credential
}
}
}
$configData = {
AllNodes = (
{
NodeName="localhost";
CertificateFile = "C:\publicKeys\targetNode.cer"
})
}
ChangeCmdBackGroundColor -ConfigurationData $configData
|
この例では、get-credential
Cmdletを使って、任意のユーザークレデンシャルを取得している。
Partial Configuration
DSCエンジンであるLocal Configuration Manager(LCM)にも更新が入った。従来、ノードとMOFの関係は1:1だったため、Configurationを一つにまとめる必要があり、管理が難しかった。しかしConfigurationを複数DSCサーバーで分割すること(Partial Configuration)がサポートされたことで、ノードに対して複数のMOFを設定可能(1:n)になり、MOFを分割して展開することが可能になった。
OSに関するConfigurationとSQL Serverに関するConfigurationを分けて取得することを考えてみよう。Partial Configurationのルールに従い、Configuration名をLCMで指定した対象と一致させればよいので、コード例17ではOSConfigServer(DSCサーバー)にはOSConfig(Partial Configuration)、SQLConfigServerにはSQLConfigを設置しておくことで、それぞれから必要なConfigurationを取得してくる。
[DSCLocalConfigurationManager()]
Configuration SQLServerDSCSettings
{
Node localhost
{
Settings
{
ConfigurationModeFrequencyMins = 30
}
ConfigurationRepositoryWeb OSConfigServer
{
ServerURL = "https://corp.contoso.com/OSConfigServer/PSDSCPullServer.svc"
}
ConfigurationRepositoryWeb SQLConfigServer
{
ServerURL = "https://corp.contoso.com/SQLConfigServer/PSDSCPullServer.svc"
}
PartialConfiguration OSConfig
{
Description = 'Configuration for the Base OS'
ExclusiveResources = 'PSDesiredStateConfiguration\*'
ConfigurationSource = '[ConfigurationRepositoryWeb]OSConfigServer'
}
PartialConfiguration SQLConfig
{
Description = 'Configuration for the SQL Server'
ConfigurationSource = '[ConfigurationRepositoryWeb]SQLConfigServer'
DependsOn = '[PartialConfiguration]OSConfig'
}
}
}
|
もちろん両方を同じサーバーに設定してもよい。
ソフトウェアデリバリー
PowerShell 5.0で最も話題になったのが、PowerShellでのソフトウェア・インストール/アンインストール機能の提供だろう。これらを使えば、yumやapt-getのようにソフトウェアやモジュールのインストールが容易に自動化できるのだ。
PackageManagement
PackageManager APIを通してNuGetやChocolateyなどさまざまなパッケージマネージャーをあたかも違いがないかのごとく透過的に扱える。つまりPackageManagement(旧名・通称:OneGet)は、パッケージマネージャーのパッケージマネージャーといえる存在だ。
利用例を見てみよう。既存のパッケージ取得先(Package Source)に加えて、Chocolateyなど、OneGetに対応したパッケージソースを追加することもできる(コード例18)。
Get-PackageProvider chocolatey
|
パッケージの検索も容易だ。OneGetではパッケージの取得先(Package Source)を指定しなければ全パッケージソースを横断して探してくれる。NuGetパッケージソースから「jQuery」を検索、Chocolateyパッケージソースから「Zoomit」を検索してみよう(コード例19)。
PS> # NuGetからjQuery検索
PS> Find-Package -Name jquery -Provider NuGet -Source http://www.nuget.org/api/v2/
Name Version Source Summary
---- ------- ------ -------
jQuery 2.1.4 http://www.nuget.org/api/v2/ jQuery is a new kind of JavaScript Li...
PS> # ChocolateyからZoomit検索
PS> Find-Package -Name zoomit -Provider Chocolatey
Name Version Source Summary
---- ------- ------ -------
zoomit 4.50 chocolatey ZoomIt is a screen zoom and annotatio...
|
必要なパッケージが見つかれば、パイプライン|
を使ってInstall-Package
Cmdletにつなぐだけでソフトウェアのインストールもできる(コード例20)。
PS> Find-Package -Name zoomit -Provider Chocolatey | Install-Package
The package(s) come from a package source that is not marked as trusted.
Are you sure you want to install software from 'chocolatey'?
[Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "N"): y
Name Version Source Summary
---- ------- ------ -------
zoomit 4.50 chocolatey ZoomIt is a screen zoom and annotatio...
|
PowerShellGet
PowerShellは、モジュール機構によって、その機能を柔軟に拡張できる。だがこれまでは、モジュールを取得・展開(=デプロイ)する手段が乏しく、標準Cmdletによるサポートもなかったことが大きな課題となっていた。PowerShell 5.0からは、PowerShellGetモジュールを利用して、マイクロソフトがホスティングするPowerShell Galleryリポジトリに公開されたモジュールの検索やインストールが可能になった。
PowerShellGetモジュールは、バックエンドにPackageManangementを利用しているため、操作に要するCmdletも似通っている。パッケージの検索Cmdletは、Find-Module
だ。そしてインストールCmdletはInstall-Module
だ。前述の「PackageManagement」の項を読まれたなら、これだけでもう利用方法が想像できるだろう。
ここでは、AzureRM.ProfileとAzureRMWebsitesという2つのモジュールをインストールしてみよう(コード例21)。
PS> Find-Module AzureRM.Profile, AzureRM.Websites | Install-Module -Scope CurrentUser
Untrusted repository
You are installing the modules from an untrusted repository. If you trust this repository, change its
InstallationPolicy value by running the Set-PSRepository cmdlet. Are you sure you want to install the modules from
'https://www.powershellgallery.com/api/v2/'?
[Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "N"): a
|
PowerShellGetによるパッケージ検索を見て、DSCリソースだけを絞って検索したくなっただろうか? もちろんそれも可能で、Find-DscResource
CmdletとInstall-Module
Cmdletを使えば、PowerShell Galleryに登録されている「DSC Resources」だけを対象に検索して、それをインストールできる。例えばコード例22は、DSCリソースのxPackage
を検索して、全ユーザーとして%ProgramFiles%\WindowsPowerShell\Modules
にインストールしている。ちなみに、DSCリソースの一覧を取得するには、単にFind-DscResource
のみをコマンド実行すればよい。
PS> Find-DscResource xPackage | Install-Module
NuGet provider is required to continue
PowerShellGet requires NuGet provider version '2.8.5.201' or newer to interact with NuGet-based repositories. The NuGet
provider must be available in 'C:\Program Files\PackageManagement\ProviderAssemblies' or
'C:\Users\admin\AppData\Local\PackageManagement\ProviderAssemblies'. You can also install the NuGet provider by running
'Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force'. Do you want PowerShellGet to install and
import the NuGet provider now?
[Y] Yes [N] No [S] Suspend [?] Help (default is "Y"): y
Untrusted repository
You are installing the modules from an untrusted repository. If you trust this repository, change its
InstallationPolicy value by running the Set-PSRepository cmdlet. Are you sure you want to install the modules from
'https://www.powershellgallery.com/api/v2/'?
[Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "N"): y
|
既存Cmdletの強化
既存Cmdletも強化されたが、やはり数が多いので、特に利用してほしい機能に絞って紹介する。
シンボリックリンク
まさに待ち望まれていた機能なのではないだろうか。従来は.NETで自前実装するか、あるいはcmd.exeに実装されているmklinkコマンドを呼ぶ必要があったが、ついにPowerShell標準でサポートされた。
シンボリックリンクの利用には管理者権限が必須だ。また、制限としてリンク先パスの存在が必須となっているので気を付けてほしい。
コード例23では、d:\hoge.txt
ファイルのシンボリックリンクとして「d:\fuga.txt」、d:\hoge
フォルダーのシンボリックリンクとして「d:\hogemoge」をNew-Item
Cmdletを使って作成している。
ファイル・シンボリック・リンクの削除処理はRemove-Item
Cmdletだ。ディレクトリ・シンボリック・リンクの削除はDirectoryInfo.Delete()
メソッドとなる。ちなみにPowerShell 4.0までは、シンボリックリンクを消そうとRemove-Item
すると、リンクではなく中のファイル/フォルダーを消してしまっていたが、PowerShell 5.0ではリンクのみが削除されるように改善された。
PS> # ディレクトリシンボリックリンクの作成
PS> New-Item -Type SymbolicLink -Path d:\hogemoge -Value d:\hoge
Directory: D:\
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----l 12/25/2015 3:37 PM hogemoge
PS> # ディレクトリシンボリックリンクの削除
PS> (Get-Item -Path d:\hogemoge).Delete()
PS> # ファイルの作成
PS> New-Item -ItemType File -Path d:\hoge.txt
Directory: D:\
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 1/16/2016 5:06 AM 0 hoge.txt
PS> # ファイルシンボリックリンクの作成
PS> New-Item -ItemType SymbolicLink -Path d:\fuga.txt -Value d:\hoge.txt
Directory: D:\
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---l 1/16/2016 5:06 AM 0 fuga.txt
PS> # ファイルシンボリックリンクの削除
PS> Remove-Item -Path d:\fuga.txt -Force
|
New-SelfSignedCertificate
New-SelfSignedCertificate
Cmdletに対する機能強化についてはリリースノートに記載されていないのだが、強く推奨したい。
PowerShell 5.0からは自己証明書を作成するときに、Windows SDKなどに同梱されているmakecertコマンドを利用する必要はなくなった(と思っている)。PowerShell 4.0までは限られた用途の自己証明書しか作れなかったが、PowerShell 5.0で大幅に強化されてmakecertがほぼ不要といえる状況になったためだ。
ローカルPCでSSL通信を開発・検証するために自己証明書を作るのも簡単だ(コード例24)。
New-SelfSignedCertificate -DnsName "www.contoso.com" -CertStoreLocation "cert:\LocalMachine\My"
|
他にも証明書のクローンが可能になっている(コード例25)。
Set-Location -Path "cert:\LocalMachine\My"
$OldCert = (Get-ChildItem -Path T71ANC3B3F2441901B3A3E35E0C3C4D5738DABC1)
New-SelfSignedCertificate -CloneCert $OldCert
|
新Cmdletの追加
ファイル圧縮/解凍操作
.NETによるZipファイルの解凍/圧縮は、.NET 4.5で提供開始されたZipArchiveクラス
でサポートされたが、PowerShell 5.0でもCmdletによる解凍/圧縮がサポートされた。圧縮するときはCompress-Archive
Cmdlet、解凍するときはExpand-Archive
Cmdletを使用する(コード例26)。
PS C:\> cd D:
PS D:\> 1..1000 | %{Get-Date} | Add-Content d:\hogemoge.txt
PS D:\> Compress-Archive -Path d:\hogemoge.txt -DestinationPath d:\hogemoge.zip
PS D:\> Get-ChildItem d:\hogemoge*
Directory: D:\
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 12/25/2015 8:08 PM 23230 hogemoge.txt
-a---- 12/25/2015 8:09 PM 227 hogemoge.zip
|
PS D:\> rm d:\hogemoge.txt
PS D:\> Expand-Archive d:\hogemoge.zip
PS D:\> ls d:\hogemoge\*
Directory: D:\hogemoge
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 12/25/2015 8:08 PM 23230 hogemoge.txt
|
クリップボード操作
クリップボードの操作も可能になったことで、PowerShellの利便性はさらに大きく向上するだろう。図4は、Windowsエクスプローラーでファイルを複数選んでコピーしてから、Get-Clipboard -Format FileDropList
を実行すると、コピーしたファイルのFileInfo
オブジェクトが出力される様子だ。
Convert-String
文字列を置換したいときに、StringオブジェクトのReplace()
メソッドや-replace
オペレーター、あるいは正規表現を使うことは多いと思う。しかしPowerShell 5.0で、それらの登場機会は減っていくことだろう。追加された新しいConvert-String
Cmdletは、サンプルパターンから法則を読み取って置換してくれる魔法のようなCmdletだからだ。
例えば、“Lee Holmes”、“Steve Lee”、“Jeffrey Snover”という名前を“Holmes, L.”、“Lee, S.”、“Snover, J.”に置換することを正規表現で考えてみてほしい。その考えている間にコード例27のConvert-String
を見ると、その便利さを納得していただけるのではないだろうか。
"Lee Holmes", "Steve Lee", "Jeffrey Snover" | Convert-String -Example "Bill Gates=Gates, B.", "John Smith=Smith, J."
|
Format-Hex
ファイルのバイナリをさくっと見たい。そんな気持ちになったことがある人は、PowerShell 5.0から追加されたFormat-Hex
Cmdletをきっと好きになるだろう。
このCmdletによって、ファイルのバイナリダンプが容易に表示できる(コード例28)。
PS> ls $env:WinDir -File | where Length -gt 200 | where Length -le 1000 | select -First 1 | Format-Hex
Path: C:\WINDOWS\system.ini
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
00000000 3B 20 66 6F 72 20 31 36 2D 62 69 74 20 61 70 70 ; for 16-bit app
00000010 20 73 75 70 70 6F 72 74 0D 0A 5B 33 38 36 45 6E support..[386En
00000020 68 5D 0D 0A 77 6F 61 66 6F 6E 74 3D 64 6F 73 61 h]..woafont=dosa
00000030 70 70 2E 66 6F 6E 0D 0A 45 47 41 38 30 57 4F 41 pp.fon..EGA80WOA
00000040 2E 46 4F 4E 3D 45 47 41 38 30 57 4F 41 2E 46 4F .FON=EGA80WOA.FO
00000050 4E 0D 0A 45 47 41 34 30 57 4F 41 2E 46 4F 4E 3D N..EGA40WOA.FON=
00000060 45 47 41 34 30 57 4F 41 2E 46 4F 4E 0D 0A 43 47 EGA40WOA.FON..CG
00000070 41 38 30 57 4F 41 2E 46 4F 4E 3D 43 47 41 38 30 A80WOA.FON=CGA80
00000080 57 4F 41 2E 46 4F 4E 0D 0A 43 47 41 34 30 57 4F WOA.FON..CGA40WO
00000090 41 2E 46 4F 4E 3D 43 47 41 34 30 57 4F 41 2E 46 A.FON=CGA40WOA.F
000000A0 4F 4E 0D 0A 0D 0A 5B 64 72 69 76 65 72 73 5D 0D ON....[drivers].
000000B0 0A 77 61 76 65 3D 6D 6D 64 72 76 2E 64 6C 6C 0D .wave=mmdrv.dll.
000000C0 0A 74 69 6D 65 72 3D 74 69 6D 65 72 2E 64 72 76 .timer=timer.drv
000000D0 0D 0A 0D 0A 5B 6D 63 69 5D 0D 0A 72 2E 64 72 76 ....[mci]..r.drv
|
まとめ
PowerShell 5.0は、過去のリリースの中でも最もコミュニティによる意見が取り込まれたリリースとなった。それは、小粒ながらうれしい新Cmdletの追加や、DSCを本番環境で利用していくのにまさに必要な機能に改善されたことからも分かるだろう。
この記事が皆さんのPowerShell 5.0への興味と理解の一助になれば幸いだ。
1. PowerShell DSCで導入された新しい構文キーワード
Windowsインフラ環境の構築を自動化できる「PowerShell DSC」とは? その使い方を紹介。DSCの構文をコードで示しながら、基本的な実践手順を説明する。
2. 本番で使えるPowerShell DSCリソース作成入門
Windows Serverの構成管理を自動化できるツール「PowerShell DSC」を使いこなそう。PowerShellでDSCのリソースを自作する方法とは?