PowerShell Core 6.0

PowerShell Core 6.0がリリースされました。ダウンロードはGitHubより各プラットフォーム用に公開されています。尚、インストールは全く別の場所に行われますので、既存のWindows PowerShellを残したまま行えるどころか、ZIPファイルでも提供されていますので、インストーラーを実行する必要でさえありません。)

PowerShell CoreはWindows PowerShellのオープンソース、クロスプラットフォーム版で、今後はWindows PowerShellの開発は5.1を最後のバージョンとし、メンテナンス程度になり、こちらの方に注力していくようです。

Windows PowerShellは.NET Frameworkベースになっていますが、PowerShell Coreは、.NET Core、正確には.NET Standardベースのものになっています。そのため、.NET Standardに準拠したライブラリなどは読み込める場合もありますが、Active Directoryなど、一部の機能は使用できませんので、そういった場合はWindows PowerShellと平行して使用することになるかと思います。

PowerShell Coreの何がいいのか?

特にLinuxやWindowsなど複数のプラットフォームを使用している場合において、同様の使用感、及び、スクリプト構文でCUIを利用することができます。尚、execなどの呼び出しに失敗し、挙動がおかしくなる場合があるので、Linux上でpwshに対してchshを行うのはおすすめできません。(目立ったところではSSHのスクリプト実行に失敗したり、Dropboxがゾンビ状態になったりします。)

.NET CoreのモジュールをCUIより呼び出すことが可能なので、例えば以下の要な構文が使えます。

(New-Guid).ToString().ToUpper()

この構文では、New-GuidはPowerShellのCmdletを使用していますが、これは[Guid]::NewGuid()とすることもでき、同じ形式の出力になります。

[Guid]::NewGuid().GetType() -eq (New-Guid).GetType()
True

実際はCmdletの実体は.NETのライブラリなので、内部的には同じような構造になっています。

Cmdletは例えば以下のような構成になっています。

using System.Management.Automation;

namespace cmdlettest
{
    [Cmdlet(VerbsCommon.Get, "Hello")]    
    public class TestModule : PSCmdlet
    {
        [Parameter(Position = 1)]
        public string Message { get; set; } = string.Empty;

        protected override void EndProcessing()
        {
            var output = "Hello World";
            if (Message != string.Empty)
                output += ", " + Message;
            WriteObject(output);
            base.EndProcessing();
        }
    }
}

これをコンパイルし、モジュールとして読み込むことで、Get-Helloのコマンドが使えるようになり、コマンドラインのパーシングなども自動で制御してくれます。もちろん一度コンパイルすると依存として読み込んでいる他のライブラリにプラットフォームの要件がない限りはPowerShell Coreを使用することのできる全ての環境で使用できます。

PowerShell Coreをダウンロードしたらまず行うべきこと

WindowsPSModulePathの導入

Windowsで使用している場合、以下のコマンドでWindowsPSModulePathを導入しておくと便利かも知れません。Windows PowerShellにより提供される一部のライブラリを使用できるようになります。

Install-Module WindowsPSModulePath -Force

ユーザーレベルで入れたい場合は以下のようにもできます。

Install-Module WindowsPSModulePath -CurrentUser -Force

その後、これは以下のコマンドで有効にできます。

Add-WindowsPSModulePath

尚、スタートアップファイルは$PROFILEですので、こちらに格納することによりPowerShell起動時に自動的に読み込まれます。

ヘルプファイルの更新

PowerShell Coreでは詳細なヘルプ情報を参照することができます。(UNIX系シェルでいうmanページのようなものです。)

これらのドキュメントは更新する必要があります。それを行うにはUpdate-Helpコマンドを使用します。このコマンドはAdministrator権限(Windows)、root権限(Linux等)で行う必要があります。(尚、Update-Helpが失敗する場合-Forceオプションをつけてやるとうまく行くかも知れません。)

どうしても更新が失敗する場合(UI Culture系の例外が発生する場合)それを無視する設定が必要になります。(日本語のヘルプはないので、英語のロケールを優先指定します。)

 -Force -ErrorAction SilentlyContinue -UICulture en-US, ja-JP

更新を行うと、例えばGet-Help Get-Processなどで参照できる他、Get-Process -?で行うこともできます。

最後に

PowerShell Coreがリリースされたことにより、Windows以外のプラットフォームでもPowerShellの利便性が享受できるようになります。スクリプトはプラットフォームを超えて動作する他、.NET Coreを使用して独自のCmdletを記述することができます。

スクリプト開発環境も整備されており、Visual Studio及び、Visual Studio Codeでスクリプトのデバッグができるようになっています。(Cmdletに関しても上記のように実体は.NETライブラリなので、.NET Core開発環境で開発可能。)

これまで特にWindowsとLinux間など共通のシェルスクリプト的な使い方ができなかったので、この点が便利です。(Windows上でUNIX系シェルを使用するにしても、WSLはほとんど別環境ですし、bashやCygwinなどもOSとしての作法が違うため、不便さがありました。)

NuGet経由で拡張が可能など、.NET Coreの機能が利用できるなど、便利な使い方ができそうです。

ReSharperが指摘してくれるコードスタイルのあれこれ

ReSharper(と同様のエンジンを内蔵しているRider)が指摘してくれるものにはいろいろな種類のものがあるのですがそのいくつかに関する考察。

Collection Initializerへの置き換え

次のようなコードがあったとします。

var list = new List();
list.Add(new Something() {unit = "One", value = 5});
list.Add(new Something() {unit = "Two", value = 6});

ReShaperは次のような置き換えを提案してきます。

var list = new List
{
    new Something() {unit = "One", value = 5},
    new Something() {unit = "Two", value = 6}
};

これは確かに冗長になりがちなのでシンプルな書き換えにするのにはいい方法。

Foreach文のLINQ式への置き換え

時々出てくるパターンとしてリストの中を辿りつつ内容に対して処理を行うパターン。foreachで辿るようなパターン、例えば次のようなパターンがあったとします。

foreach (var item in list)
{
     if (item.unit == "Two")
        result += item.value;
}

これは以下のように置き換えることを提案してきます。

var result = list.Where(item => item.unit == "Two").Sum(item => item.value);

処理が複雑になると可読性が失われたり、デバッグが複雑になったりすることがあるのでその点は注意です。

メソッドのstatic化

次のようなクラスがあったとします。

internal class Hoge
{
    private int _value;

    public int Foo(int v)
    {
        _value += v;
        return _value;
    }

    public int Bar(int v)
    {
        v -= 1;
        return v;
    }
}

ReSharperはこのうち、public int Bar(int v)をstatic化するように提案してきます。

internal class Hoge
{
    private int _value;

    public int Foo(int v)
    {
        _value += v;
        return _value;
    }

    public static int Bar(int v)
    {
        v -= 1;
        return v;
    }
}

これはインスタンス化を行うとその分、要求されるメモリが増えるので、必要がないものにおいてはVM内で共有したほうがいい、ということですね。

ただ、staticメソッドのインスタンス化はそのメンバを呼び出したタイミングで行われたり、ガーベジコレクションの挙動が普通とは異なってくるはず(というか、スコープから外れない場合は残存し続けるので、長期的に残り続ける挙動を示すはずです)のでその部分では注意が必要です。

JetBrains All Products Pack

最近JetBrainsのAll Products Packを購入したのでいろいろと。

まずはそれぞれのツールに関していろいろと書いてみる。

Rider

まずいちばん使っているのがこのRider。C#のIDEです。現段階で使っているのは.NET Core 2.0の機能を使いたいので、EAP版です。

ちなみにRiderはUnityと組み合わせ使うことも可能です。Linux版のUnity Editorと組み合わせて使用する場合に便利です。

機能面ではVisual StudioResharperを組み合わせたものに近いです。(Windows Formなどのビジュアルエディターはありませんが……。)

尚、Reshaperに関しても上位版であるResharper Ultimateが、All Products Packに含まれています。

プライベートではマルチプラットフォーム開発なので、あまり使う機会はなかったりしますが。(ただし、使う場合Visual Studio Communityでもちゃんと動作します。)

DataGrip

次によく使うのがDataGripです。DataGripはデータベース用のIDEです。

いろいろなデータベースをサポートしていて、SQL文を発行したり、内容を調べたりすることができます。

Gogland

GoglandはGoogleにより開発されている、Go用のIDEです。現在EAPで無料で使用できます。正式版では名前が変わるかも知れないようです。

IntelliJ IDEA Ultimate

IntelliJ IDEA UltimateJavaのIDEです。(正確にはJVMな言語は多くが対応しています。KotlinもJetBrainsが開発していますし、もちろん対応しています。)

尚、IntelliJ IDEA Ultimateにはオープンソース版のIntelliJ IDEA Communityも存在します。これ一本でJavaのアプリ、Androidのアプリなどを開発したりできます。プラグインを通してGoやPythonなどの他の言語も開発することができるようですが、挙動など言語特化のIDEがより言語に特化した動作をするようになっているようです。

個人的にはJavaはあまり使わないので、XSLTの編集などに使ったりする場合が多いです。

PyCharm Professional

PyCharm ProfessionalPythonのIDEです。。こちらもPyCharm Communityというオープンソース版の他、PyCharm Eduという教育目的に特化した特別版も存在します。

PhpStorm

PhpStormPHPのIDEです。あまり新規にPHPは少なくとも自分で書くことは少ないのですが、レガシーなコードはあるのでその保守に使用しています。

CLion

CLionはC/C++のIDEです。Linux上で時々C/C++を扱ったりするので、その場合に活用しているツールです。

RubyMine

RubyMineRubyのIDE。Rubyのコードは現在PHPよりも少ないのであまり出番はないですが……。

MPS

イマイチ使い方がよくわかっていないのが、このMPS。IDEというよりはメタ言語みたいなのですが……。

JetBrainsのAll Products Packは開発機材として個人的に買う場合は、そこまでは高くはないのですが(ビジネスとして買う場合はそれなりに高くなりますが……)それなりの額にはなりますが、今のところはその値打ちはあるように感じています。特に複数の言語を使う必要がある場合同じ使用感で複数の言語を扱えますので。

実行時間が短いWindowsサービスの問題について

One-shotなサービスで持続時間が短いとWindowsのサービスはエラーが起きたものとして処理する場合があるらしい。

エレガントではない方法としてはThread.Sleep()で少し遅延させてやるようなのがいいかも知れない。(C#の場合。)

機械学習の特徴などに関して

先日のニューラルネットワークはポケモンの夢を見るか、の記事ですが、記事中でも書いたように、基本的には「機械学習の余地が入る部分はあまりない」と書きましたが、その点に関してより詳しい解説を追加したいと思います。

まず、機械学習の特徴ですが、「プログラムが遭遇するケースを全て個別にプログラムをすることなく判断ができる技術」となります。通常、プログラムを組む場合、例えば、通常のアプリケーションなどではユーザーの入力に対し、どのような挙動を示すかがプログラムされています。例えば、ウェブブラウザにURLを入力するとそのページを読みだし、ウェブサイトが表示されます。これはウェブブラウザのプログラマがそのようにプログラムしたからです。

このため、すでに相性等が定義されているポケモンに関して言えば、機械学習を用いなくとも全てのケースに対しプログラムした方が信頼性が高い結果が得られることになります。(そもそもポケモン自体がそのようにプログラムされているわけです。)

上記とは異なり、機械学習が効果を発揮するのは以下のようなケースになります。

  • 入力する定義値やその組み合わせが膨大であり、全体をプログラムすることが現実的でない場合。
  • 期待される入力値に未知の部分や曖昧な部分が存在する場合。
  • 認識されるべき変化が非常に微細であるか、特徴が簡潔でない場合。(ある特徴を定義する特徴量が多く必要という点で、上記の定義値に関連します。)

上記を踏まえて、例えば、自動運転車の実現に非常に多大な労力が消費されているのは、認識する必要がある事項に関してほぼ無限の可能性があり、全てのケースに関してプログラムすることができないという点によります。(例えば、人が道に立っている、という認識をしたい場合、様々な天候や光の当り具合、人が立っている場所、その動きなどに対してその対応を全てプログラムすることは現実的ではありません。)

尚、例えば、信号などがその状況を発信したり、車同士が通信できたりすることにより、曖昧さは解消することができますので、現在は自動運転車は現行の車や環境と強調して走らせる、ということに比重を置いていますが、今後はその方面での交通インフラの検討は進むのではないかと考えます。

以前、GoogleのCEOが「自動車の方がコンピューターより先に発明されたのは間違いだった」というような発言をしていますが、そういう意味でもコンピューターが最初に発明されていれば、恐らく交通インフラ自体がそれを前提とする形になっていた、ということなのではないかと思います。

話をポケモンに戻すと、ポケモンの場合は各18種類の要素が最大2個まで重複できるような作りになっていますので、情報量的にはそこまで大きくなく、全てをプログラムするのはさほど困難ではありません。ただし、これが数百、数千となり、また重複もより多く可能などとなると全プログラムをするのは困難になってきます。(ただし、規則性を符号化することによって必ずしも全部を手作業で、ということにはなりませんが。)

ちなみに先日のポケモン要素判断のニューラルネットワークは、非常にシンプルなものというだけで、実はその延長に画像認識やその他の高度な認識があります。

今後、機械学習の「民主化」が進んでいくと思いますので、その一つとして個人的な研究テーマにしています。

ニューラルネットワークはポケモンの夢を見るか

TensorFlow(及び、ニューラルネットワーク)を使用して以前からやってみたいと思っていたことは数値処理だったりします。今回それに関して試してみることにしました。

対象を探していた時、ポケモン・サン&ムーンを見て思いつきました。フェスサークルのアトラクションに「タイプ相性 診断!」というのがあります。このミニゲームでは効果が「バツグン」なものを判断するというテーマになっています。例えば、その対象が「むし」「くさ」だと答えはほのおとなり、 「こうかはバツグン」ということになりポイントが入ります。この相性として、弱い順から「効果がない」, 「効果は今一つ」, 「普通」そして「効果はバツグン」という4つに別れます。

相性は表になっていますので、機械学習の余地が入る部分はあまりないのですが、はたして失敗から学ぶというアプローチは可能かどうかを試してみることにしました。

かなりのフェスチケットを消費して80ケース程度のログを貯めることができました。このようなデータを処理するための前処理など、初心者でありますので、何らかの参考文献を探したのですがTensorFlowは画像処理に偏った情報が多く、似たようなアプローチを取っているものとしてmtitg氏による、TensorFlowを使ったディープラーニングでタイタニックの生存予測という記事に行き当たりました。

氏の例では8個のパラメータを使用していますがポケモンでは3つのパラメーターになります。こちらで紹介されているコードはテキストのデータの前処理なども含め、非常に参考になるものでした。

こちらを当てはめたコードを使用して検証してみました。結論から言うと、80件程度のデータからは50%ほどの正答率しか得ることしかできませんでした。これは次の理由があるように思われます。

  • 手動で集めたデータであるため、データのバラエティが少なく、かなり多岐に渡るポケモンの相性の組み合わせを考えると一部しかカバーできていない。
  • 「普通」のデータが多すぎる。例えばほのおに影響を与える「むし」など、そういったものがない場合は「普通」になってしまう場合が多い。そのため、データは「普通」に傾いてしまい、他の3つのものよりも多くなってしまっている。
  • ニューラルネットワークはこの手の構造化されたデータには向かないのかもしれない。ロジスティック回帰やベイズアルゴリズムに向いた課題なのかも知れない。

結論

先に書いたように、相性のデータが存在している以上、あまり実用向けとは言えないが学習と楽しみには適切に感じました。

さらなる最適化と研究により、TensorFlowや機械学習はすでに存在するデータセットなどに対して、その中から意味ある見地を読み取るのに非常に有用であると感じ、また、さらなる価値を見出すことができるのではないかと考えます。画像認識や自動運転車など機械学習の応用として非常にクールではありますが、すでに手持ちのPCなどでこの技術を応用するという点に関して決して軽視されるべきではない分野なのではないかなと感じます。

PythonベースのノートブックシステムJupyter

最近よく使用しているツールでJupyterというのがあります。

特徴は

  • Pythonベース、元はIPythonというもので、インタラクティブなPython環境を提供するシステムだった。
    • 今はPython以外も使えるようになったので、Project Jupyterとなった。IPython自体はインタラクティブなPython環境を提供するものとして開発が続けられていて、JupyterもPython実行部分では使用している。
  • 表記記法としてMarkdown(LaTeX文法も使える!)を使用可能。
  • コード部分はノート内で実行可能。

というようなものです。(個人的にはPythonでしか使っていないので、他の言語部分については使用感などはよくわかっていません……。)

個人的に気に入っている点は

  • Pythonの様々な機能を利用できる。例えば、Tensorflowなどのライブラリも使える。目的に応じてSciPyNumPyを利用して高度な計算やプロットなどをしたり、SymPyを使用してCAS(数式処理システム)として使用できたり、Pandasや各種のPythonの内蔵のライブラリを使ってデータベースへのアクセスなどができたりします。
  • ノートは保存して共有できるので情報共有も可能。尚、nbviewerというのも存在しておりオンライン上に存在するノートブックを閲覧することも可能です。GitHubGistなどはこのため、ノートブックファイルを表示することが可能。
  • コードをPythonとして保存することも可能なため、インタラクティブに実行するPythonコード開発環境としても使える。表記したノートなどはコメントとして出力してくれる。

導入は個人的にはLinuxとWindowsで試しましたが、Anacondaを使用するのが一番楽だと思います。

(ちなみにAnaconda自体は商業プラットフォームとして追加のモジュールを販売していますので、特に業務利用などで追加のサポートや機能が必要で予算が取れる場合は、そのような方向にスケールできる、というメリットもあります。個人使用にはお高いですが……。)

もちろん特にLinuxの場合はそのままpipを使用してJupyterを入れるという方法もあります。

また気が向いたら細かい部分についても解説していきたいと思います。

LINEのLetter Sealingその後

以前、これまで、LINEのE2EE実装「Letter Sealing」初見LINEのLetter Sealingに関するフォローアップと2回に渡り、LINEのE2EE実装である、Letter Sealing機能に関して取り上げてきたわけですが、以前にも増してメッセンジャーにおけるE2EEが一般的になってきました。以前はE2EEを実装したメッセンジャーアプリはSignalTelegramぐらいしかなかったのですが、今ではFacebook傘下のWhatsappにもSignalと同じ方式のものが実装されましたし、また、Facebook MessengerもまもなくE2EEが実装されるようです。他にもGoogleもビデオチャットアプリであるDuoはE2EEを使用している他、また今後リリース予定のメッセンジャーAlloにもE2EEの実装が予定されているようです。

さて、最近、LINEのEnginners’ Blogにおいてメッセージの安全性のさらなる強化:Letter Sealingの適用拡大という記事が公開されました。内容的にはLetter Sealing機能が更新され、デフォルトでE2EEが有効となり、また、音声やビデオ通話、及びグループチャットにE2EEが使用できるようになった、ということです。

今回の更新で、以前、指摘した、暗号化されているかどうかがわかりにくい、という問題が解決したと思われます。ただ、今回の更新で、暗号化されているのがわかるようになったのですが、以前の記事で「現時点では、Letter Sealingはテキストメッセージと位置情報に対してのみ適用されます。」となっていますが、これが現在どのような実装になっているのかが気になるところです。(今回の記事でこちらの件に関しての言及はなかった。)もし、引き続き、Letter Sealingが「テキストメッセージと位置情報の対してのみ」行われているのであれば、こちらは錯誤を招く表示になってしまいますので、こちらは「何が暗号化されるのか」の詳細を知らせて欲しいところです。

次に、せっかくE2EEを実装しているのだから、もっとアピールしてもらいたいところです。現在、定点観測できるいくつかのトークグループがありますが、半分程度、この機能が有効になっていないグループがあり、そのほとんどが恐らくアプリの更新を怠っているのが原因であると考えます。LINEのユーザーは特にユーザー層が広く、技術的リテラシーにばらつきがあり、こちらは更新を促す施策を是非考えて欲しいところです。

なぜGrub2の認証脆弱性は大きな問題ではないか

Linuxのブートローダー、Grub2にバックスペースを28回押すとレスキューシェルに入れてしまうバグがあるということがこの数日報道されています。

脆弱性があるということ自体に問題があるということを否定するわけではありませんが、まず、Grub2を含む、ブートローダーの認証を過信するのが問題です。実質的にブートローダーの起動パスワードが入力できる状態であるということは即ちハード自体へのアクセスがあることを意味します。ハード自体へのアクセスが行えるのであれば、ブートローダーをUSBドライブ経由などから読み込ませて起動すれば、レスキューシェルなど、簡単に実行できてしまいます。ハードのアクセスが物理的に行える以上、この脆弱性が存在しようがしまいが、本質的にはセキュリティには全く影響しないのです。

そのため、セキュリティ問題としてこの問題を解消するには次のような施策が必要になってきます。

  • ハードへの物理的なアクセスを制限する。
  • パーティションを暗号化する。

尚、Grub2の認証機能自体、そもそも幻想のセキュリティを提供する形になってしまっていますので、本来はこんな機能自体削除しまったほうがいいぐらいです。(カジュアルな運用でレスキューシェルへ簡単にアクセスできてしまうこと自体が問題になるのであれば、ブートローダーからレスキューシェルは取り外して、必要に応じてそれを有効にしたブートローダーを外部メディア経由で起動するほうが余程マシな運用です。)

OnionShareを使用した安全なファイル共有

OnionShareを使用することにより、簡単にファイルを共有することができます。

OnionShareはTor秘匿サービスの仕組みを使用しています。秘匿サービスを使用することにより、検閲システム等に影響を受けにくく、また、点から点を暗号化された接続で結ぶことにより、第三者にファイルを預けることなく、Torのネットワークを介して、データを転送することができるようになっています。

OnionShareを使用するのに必要なものは次の二点です。

上記をダウンロードし、インストールした後は、まずはTor Browserを起動します。

TorBrowser

Tor Browserが正常に起動したのを確認した後、OnionShareを立ち上げます。

OnionShare起動後

OnionShareでファイルを選択します。

OnionShareファイル追加後

Start Sharingボタンを押します。(●表示が黄色になります。)

OnionShareファイル公開準備中

●が緑色になったら表示されている.onionアドレスを読み、受信者に伝えます。(そのままコピーすることもできます。)

OnionShareファイル公開

受け取り側はTor Browserを開いて提供された.onionアドレスを開きます。

TorBrowserで表示したOnionShare

ダウンロードのボタンを押すとダウンロードが開始されます。尚、受信者側で次のような警告が表示されることがあります。(既定で表示される。)

TorBrowserダウンロード警告

これはファイルが持つ潜在的な危険性(例えば、実行ファイルなど)を警告するものです。ZIPファイルにはそのようなファイルが入っている可能性があるため、この警告が表示されるようになっています。ダウンロードするだけでは危険はありませんが、内容物に含まれるファイルが匿名性を損なわせる可能性があることを警告している文言です。

OnionShareダウンロード完了

既定では受信者がダウンロードを完了すると、自動的に公開は停止されます。Stop sharing automaticallyのチェックを外すと自動的に停止されないので、複数の人にダウンロードしてもらう場合は、このチェックを外す必要があります。(ファイルの公開が停止された後に、再公開すると別のアドレスが生成されます。)重要なのは相手がダウンロードを完了するまで、OnionShareの共有は有効にしておく必要があります。

このようにファイルを手軽に転送できますが、特徴として以下が挙げられます。

  • 点から点への暗号化接続
  • Torに接続できている限り、ポート転送などの設定は必要なし
  • サイズの制限なし(システム上のファイルサイズの制限などに依存します。転送速度は遅めになります。)
  • Hidden Serviceが備える高い匿名性(ただし、その匿名性は当然.onionアドレスを知らせる手段により変化します。)

恒久的に、特に不特定多数にファイルを提供する場合、Webサーバを使用したHidden Serviceサイトを構築する方がいいですが、手軽にファイルを特定の相手に転送するのには便利かと思います。