しばたテックブログ

気分で書いている技術ブログです。

Nano ServerにPowerShell 6.0をインストールする

公式に手順が追加されたのでまとめてみました。

公式な手順について

公式な手順はこちら。

https://github.com/PowerShell/PowerShell/blob/master/docs/installation/windows.md#deploying-on-nano-server

PowerShell 6.0のインストール

基本的にPowerShell 6.0のインストールはWindows 10/Windows Server 2016向けのZipファイルを展開するだけでOKです。

Nano Serverは初期ビルドではInvoke-WebRequestが使えないため、公式な手順ではPowerShell DirectなどによりZipファイルを転送したうえで展開する様になっています。

指定例)

# ZipファイルはPowerShell Directなどであらかじめ転送しておく前提
Expand-Archive -Path C:\powershell-<version>-win10-win2016-x64.zip -DestinationPath "C:\Program Files\PowerShell\<version>"

ちなみに現時点で最新のWindows Updateを適用すればInvoke-WebRequestが使える様になりますので直接ダウンロードして展開しても構いません。

PowerShell Remotingエンドポイントの追加

PowerShellをインストールした後にPowerShell Remoting用のエンドポイントを追加します。

Install-PowerShellRemoting.ps1というスクリプトを実行することでWinRMにPowerShell 6.0の設定を追加し、New-PSSessionEnter-PSSessionでPowerShell 6.0に接続可能にすることができます。

このスクリプトは以下の様に-PowerShellHome-PowerShellVersionの2つの引数を指定する必要があります。
-PowerShellHomeにはインストールしたPowerShell 6.0の$PSHOME(=インストールディレクトリ)の絶対パスを、-PowerShellVersionにはバージョンに応じた任意の名称を指定します。

指定例)

.\Install-PowerShellRemoting.ps1 -PowerShellHome "<PowerShell 6.0の$PSHOMEの絶対パス>" -PowerShellVersion "<識別用のバージョン名>"

実行例)

# これはPowerShell 5.1から実行して良い
.\Install-PowerShellRemoting.ps1 -PowerShellHome "C:\Program Files\PowerShell\6.0.0.16\" -PowerShellVersion "6.0.0-alpha.16" 

なお、このスクリプトはPowerShell 5.1から実行して構いませんが、実行するには管理者権限が必要です。

また、処理の最後にWinRMサービスを再起動するのでリモートセッション中で実行すると最後にセッションが切断されてしまいますので注意してください。

そしてエンドポイントが追加された後は、New-PSSessionEnter-PSSession-ConfigurationNameパラメーターを指定することでPowerShell 6.0に接続することができます。
-ConfigurationNameパラメーターには先のInstall-PowerShellRemoting.ps1スクリプトで-PowerShellVersionに指定した名称を設定します。

指定例)

# Enter-PSSessionの場合
Enter-PSSession -ComputerName nanoserver -Credential $cred -ConfigurationName "powershell.6.0.0-alpha.16"

実行例)

PS C:\> Enter-PSSession -ComputerName nanoserver -Credential $cred -ConfigurationName "powershell.6.0.0-alpha.16"
[nanoserver]: PS C:\Users\Administrator\Documents> $PSVersionTable

Name                           Value
----                           -----
PSRemotingProtocolVersion      2.3
CLRVersion
BuildVersion                   3.0.0.0
PSVersion                      6.0.0-alpha
WSManStackVersion              3.0
SerializationVersion           1.1.0.1
PSEdition                      Core
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
GitCommitId                    v6.0.0-alpha.16

ちなみにエンドポイントの情報はGet-PSSessionConfigurationで確認することができ、実際に見てみると以下の様になっています。

[nanoserver]: PS C:\> Get-PSSessionConfiguration -Name "powershell.6.0.0-alpha.16" | Format-List *


AutoRestart                   : false
Uri                           : http://schemas.microsoft.com/powershell/powershell.6.0.0-alpha.16
PSVersion                     : 5.0
OutputBufferingMode           : Block
MaxConcurrentUsers            : 5
RunAsPassword                 :
MaxShells                     : 25
MaxConcurrentCommandsPerShell : 1000
SDKVersion                    : 2
ExactMatch                    : true
XmlRenderingType              : text
RunAsUser                     :
IdleTimeoutms                 : 7200000
Name                          : powershell.6.0.0-alpha.16
SecurityDescriptorSddl        : O:NSG:BAD:P(A;;GA;;;BA)S:P(AU;FA;GA;;;WD)(AU;SA;GXGW;;;WD)
RunAsVirtualAccount           : false
RunAsVirtualAccountGroups     :
SupportsOptions               : true
MaxShellsPerUser              : 25
MaxProcessesPerShell          : 15
Filename                      : C:\Windows\System32\PowerShell\6.0.0-alpha.16\pwrshplugin.dll
ResourceUri                   : http://schemas.microsoft.com/powershell/powershell.6.0.0-alpha.16
ProcessIdleTimeoutSec         : 0
MaxMemoryPerShellMB           : 1024
Enabled                       : True
ParentResourceUri             : http://schemas.microsoft.com/powershell/powershell.6.0.0-alpha.16
xmlns                         : http://schemas.microsoft.com/wbem/wsman/1/config/PluginConfiguration
lang                          : en-US
UseSharedProcess              : false
Architecture                  : 64
MaxIdleTimeoutms              : 43200000
Capability                    : {Shell}
Permission                    : BUILTIN\Administrators AccessAllowed

Nano ServerにPowerShell 6.0を一発でインストールする

私は以前からNano Serverへのインストールを試していたので、上記の手順を一発で行うスクリプトを作っていました。
スクリプトはGistに登録しています。

gist.github.com

このスクリプトではZipファイルとInstall-PowerShellRemoting.ps1をダウンロードしインストールを実行します。
ダウンロードは自前でやっているのでInvoke-WebRequestが無い環境でも動作します。

リモートセッションからこのスクリプトをコピペして実行すればよしなやってくれるはずです。
コピペしやすいようにスクリプトをBASE64エンコードしたバージョンも用意しあります。

最後に

とりあえずこんな感じです。
いずれは公式に一発インストールできるインストーラーが出るとは思います。

Grav CMSを試してみる

正直作業記録です。
あまり役に立つことは無いかもしれません。

はじめに

個人的にちょっとしたサイトを作りたくなり*1、Markdownを扱えるフラットファイルCMSを探してみたところ、Grav CMSが良さそうだったので試してみることにしました。

getgrav.org

CMSには特段詳しくないでですが、今回Gravを選定した理由としては、

  • Markdownを扱える(必須)
  • フラットファイル型である(必須)
  • コードのシンタックスハイライトができるプラグインがある(必須)
  • 公開されているテーマのデザインが良い
    • 特にLearn2テーマが作りたいサイトにぴったりだったので

あたりになります。

今回はとりあえずローカル環境(Windows 10)で動かすところまでやってみます。

Grav CMSを試してみる

1. PHPのインストール

GravはPHP製ですので、まずはPHPをインストールします。

現在のバージョン(Ver.1.1.17)ではPHP 5.5.9以上が必要です。
いまのところバージョンの縛りもありませんので、私は最新のPHP 7.1.2を使うことにします。

公式サイトからPHP 7.1.2をダウンロードし、適当なディレクトリに展開します。

今回はC:\PHP\7.1.2\に展開しました。
あとはこのディレクトリにPATHを通せばOKです。
私はPHPを常用しないので必要な時だけPATHを通すことにしました。 

# PHPのインストール
Invoke-WebRequest -Uri "http://windows.php.net/downloads/releases/php-7.1.2-Win32-VC14-x64.zip" -OutFile ".\php-7.1.2-Win32-VC14-x64.zip"
Expand-Archive ".\php-7.1.2-Win32-VC14-x64.zip" -DestinationPath "C:\PHP\7.1.2\"

# PHPは常用しないので利用時だけPATHを通すことにする
$env:PATH += ";C:\PHP\7.1.2\"

また、環境によってはVC14 Runtimeのインストールが必要になりますので、必要があればインストールしてください。

2. php.iniの設定

Gravでは以下の拡張機能を使用するため、php.iniの設定が必要です。

  • gd
  • mbstring
  • curl
  • openssl

今回はとりあえずphp.ini-developmentをコピーし、以下の箇所を修正しました。

; php.ini

; extension_dirのコメントを解除
extension_dir = "ext"
; 以下の拡張のコメントを解除し有効化
extension=php_curl.dll
extension=php_gd2.dll
extension=php_mbstring.dll
extension=php_openssl.dll

3. Gravのインストールと起動

GravのインストールはZipをダウンロードして展開するだけです。
コア機能のGRAV COREと管理者用UIのついたGRAV CORE + ADMIN PLUGINの二種類選べますが、今回はGRAV COREにします。

# 別に手動で解凍しても構いませんが折角なので...
Invoke-WebRequest -Uri "https://getgrav.org/download/core/grav/1.1.17"-OutFile ".\grav-v1.1.17.zip"
Expand-Archive ".\grav-v1.1.17.zip" -DestinationPath ".\grav-v1.1.17"

今回はPHPのビルトインウェブサーバーを使ってGravを起動します。
先ほどのZipを展開したフォルダに移動し

php -S localhost:[ポート番号] system/router.php

を実行すればOKです。

実行例)

cd ".\grav-v1.1.17\grav\"
php -S localhost:8000 system/router.php

実行結果はこんな感じ。

f:id:stknohg:20170219222423p:plain

この状態でhttp://localhost:8000/にアクセスすると以下の様になります。

f:id:stknohg:20170219222504p:plain

ちなみに設定にエラーがあると以下の様になり、エラーを教えてくれます。
(これはgd拡張を有効にするのを忘れていた際に出たエラーです)

f:id:stknohg:20170219222611p:plain

これでGravのインストールは完了です。

あとは\user\配下の各設定を修正すれば自分の好きなサイトを作ることが出来ます。
コンテンツを修正するだけなら\user\pages\配下のmarkdownを修正するだけでOKです。

4. プラグインのインストール

Gravではプラグインを追加することで必要な機能を追加することができます。

getgrav.org

私の作りたいサイトではコードのシンタックスハイライトが必須なので、この機能を提供してくれるPrism Highlighterプラグインをインストールします。

Gravをインストールしたフォルダの\bin\フォルダに管理用のCLIコマンドが用意されており、このコマンドを使うことでプラグインをインストールすることができます。

プラグインをインストールするコマンドの書式は以下となります。

bin/gpm install pluginname

今回はWindows環境なのでShebangが使えないのため都度phpコマンドから呼び出す必要があり、Prism Highlighterをインストールするには以下の様にします。

php .\bin\gpm install prism-highlight

ここまで書いておいてアレなのですが、Prism Highlighterはこのコマンドからのインストールに対応していないそうで、実際にこのコマンドを使うと処理自体は完了するのですが、作成されるフォルダ名が不正になってしまします。
このため、以下の様にフォルダをリネームする必要があります。

# プラグインのフォルダ名がおかしいので直す
mv .\user\plugins\prism-highlight\ .\user\plugins\prism

Prism Highlightergit cloneでインストールするのが正しいやり方だそうです。

# git cloneでPrism Highlighterをインストール
cd .\user\plugins\
git clone https://github.com/alvr/grav-prism-highlight.git prism

Prism Highlighterの細かい設定については割愛しますが、インストールした結果は以下の様になり良い感じにコードのハイライトが有効になっています。

f:id:stknohg:20170219224858j:plain

5. テーマをインストールする

最後にテーマをインストールします。
プラグイン同様テーマもコマンドからインストールします。

getgrav.org

Learn2テーマをインストールするには以下の様にします。
また、

php .\bin\gpm install learn2

テーマをインストールした後はsystem.yaml(\user\config\system.yamlのほう)を修正することでテーマを変更します。

pages->themeの設定をデフォルトのantimatterからlearn2に変えればOKです。

# system.yaml
pages:
  theme: learn2

これでテーマの変更は完了です。

learn2テーマは他のテーマとドキュメントの構造が異なるため、デフォルト設定であるdefault.mdファイルのままだと表示エラーになりますのでドキュメントの名称をchapter.mddocs.mdにして適宜対応してください。

こちらも細かい設定については割愛しますが適用した結果は以下の様になります。

f:id:stknohg:20170219225408j:plain

最後に

とりあえずこんな感じです。

今回はローカルの環境でとりあえず動かすところだけやりましたが、Gravの設定や運用環境への展開については公式ブログのチュートリアルを参考にするのが良さそうです。

getgrav.org

ちなみにAzureへの展開についてはしばやん先生のブログがとてもわかりやすく参考になります。

blog.shibayan.jp

*1:つくるサイトについては具体的な形になったらお知らせしたいですね...

PowerShellのSort-ObjectコマンドレットでIPアドレスのソートを行う

小ネタです。

orebibou.com

こちらの記事を見てPowerShellでもやってみました。

サンプルデータ

元記事と同じデータ(test.txt)を使います。

192.168.0.102
192.168.0.8
192.168.0.97
192.168.0.68
192.168.0.99
192.168.0.66
192.168.0.24

普通のソート結果はこんな感じです。
単純な文字列のソートになるので元記事同様に欲しい形にはなりません。

f:id:stknohg:20170215220431p:plain

version-sort

こちらは、私は最初思いつかなかったのですが、牟田口先生があっさり書いてくれました。流石です。

cat .\test.txt | sort {[Version]$_}

結果はこちら。

f:id:stknohg:20170215220506p:plain

解説

PowerShellのsort(Sort-Object)では-Propertyパラメーターでソートに使うプロパティを指定することができ、そのプロパティにスクリプトブロックによる式を指定することができます。

sort {[Version]$_}

の部分をより正確に書くと、

Sort-Object -Property { [Version]$_ }

となり、入力値の文字列$_(192.168.0.102など)をSystem.Versionクラスにキャストした結果でソートできる様になります。
これは、.NET Frameworkのバージョン指定が、[Major].[Minor].[Revision].[Build]とIPアドレスと同じ書式なため利用できる方法です。

各オクテットごとにソート

こちらは私が最初に思いついた方法です。
元記事同様に各オクテット順でソートします。

cat .\test.txt | sort (0..3|%{[ScriptBlock]::Create("[int]$`_.Split('.')[$_]")})

結果はこちら。

f:id:stknohg:20170215222853p:plain

解説

上記の

(0..3|%{[ScriptBlock]::Create("[int]$`_.Split('.')[$_]")})

の部分を展開すると、

{[int]$_.Split('.')[0]}, {[int]$_.Split('.')[1]}, {[int]$_.Split('.')[2]}, {[int]$_.Split('.')[3]}

となり、最終的なコマンドは

Sort-Object -Property ({[int]$_.Split('.')[0]}, {[int]$_.Split('.')[1]}, {[int]$_.Split('.')[2]}, {[int]$_.Split('.')[3]})

となります。
-Propertyでは入力値の文字列$_(192.168.0.102など)を.でスプリットした結果(各オクテット)を順にソート対象にしています。

2017/02/17追記 別解

元のデータが文字列なので、桁数が揃っていれば期待したソートをさせることが可能です。
なので別解として、

cat .\test.txt | sort { -join $_.Split('.').PadLeft(3)}

も可能です。

f:id:stknohg:20170217125211p:plain

この方法では入力文字列を、

192168  0102
192168  0  8
192168  0 97
192168  0 68
192168  0 99
192168  0 66
192168  0 24

の様に変換して桁数を揃えています。

最後に

とりあえずこんな感じです。
PowerShellのソートはかなり自由度が高く、何でもありな感じがしますね。