PowerShell on linux


PowerShellがLinuxにポーティングされたようなので試してみた記録です


#モノ
githubで公開されています
https://github.com/PowerShell/PowerShell/releases/latest
ソースも公開されているので実装の確認もできるようです

#インストール
ドキュメントはこちら
https://github.com/PowerShell/PowerShell/blob/master/docs/installation/linux.md

CentOS7だとパッケージを落として
https://github.com/PowerShell/PowerShell/releases/latest

```sudo yum install powershell-6.0.0_alpha.9-1.el7.centos.x86_64.rpm```

だけですね

環境変数PSHOMEを設定します
```export PSHOME='/opt/microsoft/powershell/6.0.0-alpha.9/'```



#実行
$ /opt/microsoft/powershell/6.0.0-alpha.9/powershell


ファイル名と時刻の一覧を出力してみます
bashだとこんな感じのモノ

```
$ ls -l | awk '{print $9","$6"/"$7"/"$8}'
,//
./,Feb/17/2016
../,Feb/17/2016
bin,Feb/17/2016
boot/,May/23/15:16
dev/,May/23/15:15
etc/,Aug/19/14:26
home/,Feb/29/19:05
lib,Feb/17/2016
lib64,Feb/17/2016
man/,Dec/1/2014
media/,Aug/12/2015
mnt/,Aug/12/2015
opt/,Aug/19/14:26
proc/,Feb/17/2016
root/,Apr/19/14:35
run/,Aug/19/14:26
sbin,Feb/17/2016
srv/,Aug/12/2015
sys/,Feb/17/2016
tmp/,Aug/22/10:22
usr/,Feb/17/2016
var/,Apr/19/14:39
```


Powershellではオブジェクトが使えるので

```
PS /> dir |foreach {Write-Host $_.name","$_.LastWriteTime}
bin , 2/17/16 4:58:42 PM
boot , 5/23/16 3:16:52 PM
dev , 5/23/16 3:15:40 PM
etc , 8/19/16 2:26:22 PM
home , 2/29/16 7:05:47 PM
lib , 2/17/16 4:58:42 PM
lib64 , 2/17/16 4:58:42 PM
man , 12/1/14 11:52:52 AM
media , 8/12/15 11:22:27 PM
mnt , 8/12/15 11:22:27 PM
opt , 8/19/16 2:26:22 PM
proc , 2/17/16 6:01:19 PM
root , 4/19/16 2:35:08 PM
run , 8/19/16 2:26:24 PM
sbin , 2/17/16 4:58:42 PM
srv , 8/12/15 11:22:27 PM
sys , 2/17/16 6:01:24 PM
tmp , 8/22/16 10:22:56 AM
usr , 2/17/16 4:58:43 PM
var , 4/19/16 2:39:38 PM
```



上記の`dir`を`ls`にしても期待された動作はしません。
lsなどのOS側のコマンドをPowerShellのパイプに渡しても文字列として渡されるので出力解析はいままで通りのやり方が必要になります。
オブジェクトとして受け渡しを行いたいのであればPowerShellのコマンドや.NETオブジェクトを利用します。


#シェルとしての利用
コマンド次第ですが非同期処理が実装されているのでインフラ屋的には並列処理がやりやすくなっています。
半面threadを意識するプログラミングが必要になるのでそこはpython/rubyとbashの中間くらいの位置づけでしょうか。



#.NETとして
ざっと触ってみたところ文字エンコード周りは少し手を加える必要があるようです。
下記のコードはWindowsでは動きますがLinuxでは文字エンコードの関係でbodyの読み込み(ReadStringAsync)でエラーになります。

```ex.Webクロール
$http = New-Object System.Net.Http.HttpClient  
$res = $http.GetAsync("https://www.google.com/")
$res.Result.Content.ReadAsStringAsync()
```


```Text:キャラクタセット
on windows

PS C:\> [System.Text.Encoding]::GetEncoding(932)

BodyName          : iso-2022-jp
EncodingName      : 日本語 (シフト JIS)
HeaderName        : iso-2022-jp
WebName           : shift_jis
WindowsCodePage   : 932
IsBrowserDisplay  : True
IsBrowserSave     : True
IsMailNewsDisplay : True
IsMailNewsSave    : True
IsSingleByte      : False
EncoderFallback   : System.Text.InternalEncoderBestFitFallback
DecoderFallback   : System.Text.InternalDecoderBestFitFallback
IsReadOnly        : True
CodePage          : 932


on Linux
PS /> [System.Text.Encoding]::GetEncoding(932)                                                                       
Exception calling "GetEncoding" with "1" argument(s): "No data is available for encoding 932. For information on 
defining a custom encoding, see the documentation for the Encoding.RegisterProvider method."
At line:1 char:1
+ [System.Text.Encoding]::GetEncoding(932)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : NotSupportedException
 
 ```


~~日本語まわりはこれからという感じなので内部で文字エンコード変換を行うオブジェクトは下記のようにバイトストリームで受け取ってから変換なり解析なりをするのが現状かと思います。α版なので正式版では対応されることをいのります。~~


~~```
　$http = New-Object System.Net.Http.HttpClient
　$res = $http.GetAsync("https://www.google.com/")
　$res.Result.Content.ReadAsByteArrayAsync()
　[System.Text.Encoding]::UTF8.GetString($res.Result)
```~~ 


おまじない（？）すればそのままいけるとのコメントを頂きましたので修正します。

```
　[System.Text.Encoding]::RegisterProvider([System.Text.CodePagesEncodingProvider]::Instance)
　$http = New-Object System.Net.Http.HttpClient
　$res = $http.GetAsync("https://www.google.com/")
　$res.Result.Content.ReadAsByteArrayAsync()
　[System.Text.Encoding]::UTF8.GetString($res.Result)
```

Windowsではsjisがデフォルトだからそのまま動くようですね。
元がWindows用なのでどのプラットフォームでも動くようにするにはちょっと気を付けないといけないところでしょうか。

```
PS C:\> [System.Text.Encoding]::Default


BodyName          : iso-2022-jp
EncodingName      : 日本語 (シフト JIS)
HeaderName        : iso-2022-jp
WebName           : shift_jis
WindowsCodePage   : 932
IsBrowserDisplay  : True
IsBrowserSave     : True
IsMailNewsDisplay : True
IsMailNewsSave    : True
IsSingleByte      : False
EncoderFallback   : System.Text.InternalEncoderBestFitFallback
DecoderFallback   : System.Text.InternalDecoderBestFitFallback
IsReadOnly        : True
CodePage          : 932
```