tech.guitarrapc.cóm

Technical updates

.NET Framework を PowerShell DSC でインストール自動化

Connectでの .NET Framework CoreのRCに感化されたわけではないのです。が、.NET Framework 4.6.1 RC1が先月でています。

https://blogs.msdn.com/b/dotnet/archive/2015/10/29/announcing-net-framework-4-6-1-rc.aspx

それも受けて、.NET Frameworkのインストールを自動化しようと思ったのですが、公式、コミュニティともに既存のDSCリソースには.NET Frameworkのインストール可能なものがないので作りました。今回はその紹介です。

GitHub

ver.3.6.0から入っています。

https://github.com/guitarrapc/DSCResources/releases/tag/ver.3.6.0

なぜ DSC でインストールを制御したいのか

.NET Frameworkは、.NETのインフラ基盤なのでこれを数百台にスクリプトや人力展開とか刺身たんぽぽ業は間違ってもやってはいけません。

スクリプト展開は規模が小さいならいいのですが、

  • 環境に応じてパラメータを変えて実行する
  • 実行結果が将来も適用されていることを保証する

といった、継続的にあるべき状態を維持する仕組みを作るのは面倒なのです。DSC (あるいはChefなど)を使うのはそういう理由もあります。

さくっと捨てて、サクッと起動するので、1回だけ走らせればok。も事実ですが、展開状況が見やすいか、保証されているか。というのも考慮して選べばいいでしょう。

前提

GraniResourceにGrani_DotNetFrameworkを作りました。

ので、 GraniResourceをモジュールパス$env:ProgramFiles\WindowsPowerShell\Modulesに配置しておきましょう。

インストール

ダウンロードからインストールまで行っています。*1

https://gist.github.com/guitarrapc/dc8464775016c163e46e

パラメータを説明します。

KB

.NET Frameworkは、インストールされると実質KB扱いになります。またOS環境によって、同じ.NET FrameworkでもKBが変わるのでご注意ください。

今回作成したリソースは、OS環境を透過的に扱うためKBで判別することにしました。

KB自体はMicrosoftから公開されているので見ればいいでしょう。

OS 場所 KB
Windows 8 または Windows Server 2012 [コントロール パネルの [インストールされた更新プログラムの Microsoft Windows の更新プログラム」 KB3045562
Windows 8.1 または Windows Server 2012 R2 [コントロール パネルの [インストールされた更新プログラムの Microsoft Windows の更新プログラム」 KB3045563

Ensure

インストールされていてほしいなら、Presentを指定します。アンインストールされてほしいならAbsentを指定します。

InstallerPath

このリソースは、.NETFrameworkのオフラインインストーラを前提としています。IntallerPathに.NETFrameworkのオフラインインストーラのフルパスを指定します。

NoRestart

DSCには、コンフィグレーションの適用後に再起動するスイッチがあるので、その制御です。

.NET Framework自体は、/norestartでインストールされています。

LogPath

ログの掃き出し先にどうぞ。

アンインストール

すでにインストールされていたら、アンインストールしてくれます。インストールされていなければ何も設定しません。

https://gist.github.com/guitarrapc/483c3d7bc902ad185597

シンプルですね。KBとEnsureさえ渡せばokです。これも実行後に再起動するかは選択してください。

インストール判定について

.NET Frameworkは、インストール判定にいくつかの手段が考えられます。

  1. ログの文字列解析
  2. レジストリでの判別
  3. ファイルでの判別
  4. KBでの判定

今回利用したのは、KBでの判定です。

ログの文字列解析

なしです。おしまい。

レジストリでの判別

これはMSDNでも推奨されています。

https://msdn.microsoft.com/en-us/library/ee942965.aspx#Anchor_5

以下のレジストリパスをみることで確認できます。

https://gist.github.com/guitarrapc/3e2eded77db734ee529d

が、この反映はインストール後の再起動後です。オンタイムでの確認ができない時点でありえないですね。おしまい。

.NET Framework 4.6 installed on all OS versions other than Windows 10の場合は393297になっているか確認となります。

ファイルでの判別

よくあるのが、C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFrameworkや、C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFrameworkですがなしですね。

バージョン判定まではここでは確定できません。おしまい。

KB での判定

.NET FrameworkがKB扱いであることを利用するのが一番素直でしょう。

再起動なしにオンラインで確認できるので、テストも容易です。今回のリソースは、そのKBを判定することを前提にしています。

幸いにも、インストーラーによるプロセスのExit Code判定も公開されているので容易です。

.NET FrameworkのアンインストールはKBのアンインストール。ここを .NETでやるのはちょっとつらさがあるので、wusa.exeの利用が一番素直かなと。

ここまで考えると、実装と、確実性とコストパフォーマンスを考えるとKBが一番いいと判断しています。

.NET 4.6 のアドバイサリについて

.NET 4.6では末尾最適化に関してRyuJITでバグが報告されています。特定の状況で発生しうる、RyuJITの末尾最適化に関するバグがあったよということです。

https://blogs.msdn.com/b/dotnet/archive/2015/07/28/ryujit-bug-advisory-in-the-net-framework-4-6.aspx

https://nickcraver.com/blog/2015/07/27/why-you-should-wait-on-dotnet-46/

これに関してはKBが発行されているのでいれればokです。

[MS15-092] .NET Framework の脆弱性により、特権が昇格される (2015 年 8 月 11 日)

また、4.6.1 RC1では当該問題は発生しません。

KBをインストールすればいい環境やその他RyuJIT起因の問題かの切り分け

アドバイサリーにあるようにRyuJIT無効化と末尾最適化の無効化で状況を切りわければいいのです。

  • If you run into an issue that you cannot diagnose, try disabling RyuJIT. (再現するか調査できない環境なら RyuJIT 無効化)
  • If disabling RyuJIT resolves the issue, please re-enable RyuJIT and disable tail call optimization.(RyuJIT 無効化で当該問題がでないなら、RyuJIT有効かして 末尾最適化を無効化)
  • If your issue is mitigated with the tail call optimization disabled, then you know that your app is subject to this issue. You can run your app in production in that configuration (tail call optimization disabled), to get the other .NET Framework 4.6 benefits. This work around will disable only the tail call optimization feature and should not negatively impact performance.(もし末尾最適化無効化で問題がでなくなったなら該当していることがわかる。プロダクションでも RyuJIT有効、末尾最適化無効で走らせることができるでしょう。4.6の他のメリットを享受できるし、悪い影響は他には基本的にはないはず。)
  • If your issue is not mitigated with the tail call optimization disabled, but is mitigated with RyuJIT disabled, we want to hear from you on .NET Framework Connect. You can also run your app in production in this configuration (RyuJIT disabled).(末尾最適化無効でも問題があって、RyuJIT無効で問題でないなら .NET Framework Connect で報告がほしい。プロダクションでも RyuJIT 無効で実行できる。)
  • If your issue is not mitigated by disabling RyuJIT or tail call optimization, then it something else and unrelated to this advisory.(RyuJIT 無効化でも末尾最適化無効でも問題が改善しない場合、このアドバイサリとは別問題の可能性がある。)

それぞれの無効化方法

KBを入れれば関係ありませんが、それ以外でRyuJITなどで問題が起こったときのために使うのもありでしょうか。 すでに公開されています。

まとめ

刺身タンポポだめ絶対

*1:ここではRyuJITの末尾最適化に関するKBのインストールを含んでいません

はじめようWindows PowerShell [Kindle版] を読んでみた

Twitterを眺めていると、SQLとAzureのこわい人が気になることをおっしゃっていました。

Masayuki Ozawa (@Masayuki_Ozawa) November 19, 2015

Masayuki Ozawa (@Masayuki_Ozawa) November 20, 2015

前々から読もうと思ってたので、いい機会なので読んでみました。

http://www.amazon.co.jp/%E3%81%AF%E3%81%98%E3%82%81%E3%82%88%E3%81%86Windows-PowerShell-%E6%9F%8F%E5%8E%9F%E5%9F%BA%E8%A6%8F-ebook/dp/B017LJOCJ2/ref=sr_1_1?ie=UTF-8&qid=1447980602&sr=8-1&keywords=%E3%81%AF%E3%81%98%E3%82%81%E3%82%88%E3%81%86Windows+PowerShell

著者様

@m0t0k1m0t0k1さんです。

https://Twitter.com/m0t0k1m0t0k1

ここでご本人も紹介しています。

http://m0t0k1×2.tumblr.com/post/132636489419/%E3%81%AF%E3%81%98%E3%82%81%E3%82%88%E3%81%86Windowspowershell%E3%81%AE%E9%9B%BB%E5%AD%90%E6%9B%B8%E7%B1%8D%E3%81%8Camazon%E3%81%A7%E3%82%82%E8%B3%BC%E5%85%A5%E3%81%A7%E3%81%8D%E3%82%8B%E3%82%88%E3%81%86%E3%81%AB%E3%81%AA%E3%82%8A%E3%81%BE%E3%81%97%E3%81%9F

感想

面白かったです。20分程度で読み終わるぐらいの分量なので気軽に読むにもいいです。

誰向け?

まえがきにもありますが、「PowerShellをシステム管理者向けのシェルだと思っている方。PowerShellをもっと気楽に使い始めてみたい」と思っている方にぜひどうぞ。*1

非常に同感ですし、私にとってPowerShellとは「さくっと何か実行するときに走らせる実行環境」です。*2 実際、「C#ばかり書いているけど裏で勝手に自動化が回ってる」という環境で働いています。この自動化を実行する環境の1つがPowerShellなだけです。

内容

「ざっくりしつつも、とりあえず誤解が少なく触れるようになる」ぐらいの温度感です。

変数の定義から、基本的な構文までざっくりまとまって書かれています。全般的に踏み込んだ説明を避けていらっしゃるのでとっつきやすいです。一番細かく説明されているのがExecution Policyなのは、ご本人がPowerShell最大の壁とお考えのためでしょうか。

素晴らしいのは、それぞれに関してソースを明示した上で基本的な説明を欠かされていないことです。読んでてためになりました。

GUIのセクションで、$this$thisに触れてられてます。これはうっかり忘れるんですがにいい説明ですね!

気になる点

いくつか古い記述やアンチパターン、理解が怪しそうなところもあって気になりました。

PSObject

直接New-Object PSObjectして触るのは、ほぼオワコンです。

クラスベース構文が出るのもそうですが、PowerShell 3.0で追加された特殊な型[PSCustomObject]が出てからは、実行効率/記述性の両面で[PSCustomObject]はオワコンです。

この章にある、Add-Memeberは使うシーンも稀にあるのですが、これもクラスベース構文でもともと少ない頻度がさらに減るでしょう。

http://tech.guitarrapc.com/entry/2013/06/25/230640

PSObjectを直で利用するのは、Select-Object {Name = ""; Expression = {}}同様にかなりパフォーマンスも悪いのでもんにょりですね。

パイプライン

PowerShellのパイプラインに関しては、逐次処理が最大の特徴です。

これは、LINQ同様に無限リストを受け、パイプライン中のオブジェクトを自在に操作できることを意味しています。ただ単純にデータをつなぐことができる、流れてきた文字列を操作できるという以上の意味があるのです。*3

無限リストの例としては、EtwStreamの待ち受けがいいでしょう。

http://pierre3.hatenablog.com/entry/2015/11/14/123032

機会があれば、もう少し踏み込んでほしいですね!

パラメータ

[Parameter(Position = 0)]を使った位置パラメータ利用は非推奨です。パラメータ名なしで関数やCmdletを実行することは、PSScriptAnalyzerでも検出されるアンチパターンとなっています。利用シーンにもよりますがあまり推奨ではないです。

http://blogs.msdn.com/b/powershell/archive/2015/04/29/scriptanalyzer-in-github-and-availability-on-powershell-gallery.aspx

https://github.com/PowerShell/PSScriptAnalyzer/blob/f5cb4fcafa2186d17758447ff01122e91110a256/RuleDocumentation/AvoidUsingPositionalParameters.md

また、[Parameter(ParameterSetName = "hoge")]に関して記述があります。そういえばブログで書いてなかったのですが、この利用は注意が必要です。特に、[Parameter(ParameterSetName = "hoge")]での[Parameter(ParameterSetName = "hoge")]無しに利用するのはあまりいい例示ではないと感じます。デフォルトでどう動作するかがないのは、かなり危険なので。これに関しては、PSScriptAnalyzerにIssueを上げては起きました。Positional Parameterではじく考えならいいので、実装書くかは微妙ですがあったほうがいいレベルではあります。

https://github.com/PowerShell/PSScriptAnalyzer/issues/366

外部ファイルを実行

ここで、Invoke-Expressionに触れていますが、これはInjectionをもたらす可能性があり、PowerShellで最も使ってはいけないCmdletです。実際、PSScriptAnalyzerでも検出されます。

https://github.com/PowerShell/PSScriptAnalyzer/blob/f5cb4fcafa2186d17758447ff01122e91110a256/RuleDocumentation/AvoidUsingInvokeExpression.md

通常の処理ではめんどくさい記述もInvoke-Expressionを使うと驚くほど簡潔に書けるのですが、危険度ナンバーワンなので使っちゃだめです。

モジュール

ここで以前書いた記事が紹介されていました。ありがとうございますありがとうございます。

http://tech.guitarrapc.com/entry/2013/12/03/014013

私個人としては、モジュールはバイナリモジュールかマニフェストモジュールですにゃ。スクリプトモジュールだと制御しにくいことが制御できるので。

モジュール機構は、そろそろ負の遺産が目立ってきているのでこの辺はそろそろ一新してほしいですねぇ。

function と filter

filterは、確かに使うシーンは少ないですが、かなり便利でできる子です。再評価されてもいいレベルで。

PowerShellはScriptBlockをもう少し進化させてほしいんですが、filterあたりうまく使ってくれないかなぁとか思ったり。

まとめ

PowerShellわからないので勉強になりました!

*1:ライセンスポリシーに、「本書の全部、または一部の複写、複製、転載を禁じます」とあるので、私が受け取った意味合いで書いています。

*2:そういう意味でC# REPLを待ってるのです

*3:ただし外部コマンドファイルを除くhttp://tech.guitarrapc.com/entry/2014/02/10/221121