読者です 読者をやめる 読者になる 読者になる

銀の光と碧い空

クラウドなインフラとC#なアプリ開発の狭間にいるエンジニアの日々

Linux の dotnet restore は大文字HTTP_PROXYを認識しない、あるいは curlコマンドは大文字HTTP_PROXYを認識しない件

.NET Core C#

微妙にハマったので、書いておきます。.NET Core CLI のdotnet restoreコマンドをプロキシ環境下のLinux*1で使う場合、環境変数http_proxyは小文字で設定する必要があります。ちなみにこれはcurlコマンドでも同じです。ちなみにhttps_proxyもしくはHTTPS_PROXYはどちらでも動くのですが、少し挙動が異なるので最後に補足します。

man curl からの抜粋

The environment variables can be specified in lower case or upper case. The lower case version has precedence. http_proxy is an exception as it is only available in lower case.

せっかくなのでコードを追ってみましょう。dotnet restoreはNuGet.Coreを参照してつかっています。環境変数http_proxyのキーはここで定義されています。

NuGet.Client/ConfigurationContants.cs at 3.4.5 · NuGet/NuGet.Client · GitHub

そして、ここで環境変数を取得していますが、この時大文字小文字は区別していません。

NuGet.Client/ProxyCache.cs at 3.4.5 · NuGet/NuGet.Client · GitHub

つまり、大文字でHTTP_PROXYをセットしてもLinux*2では無視されてしまうのです。また、この後のコードを見るとわかるようにURLのチェックをしているので、不正なURLを指定すると警告なしで無視され、プロキシなしでアクセスを試みます。ちなみに認証付きプロキシの場合は、http://user:passowrd@host/http://<username>:<password>@proxy.comの形式で指定すれば動くらしいのですが、手元に認証つきプロキシの環境をすぐに用意できていないので、検証していないです。 また、NuGetのAPIエンドポイントはhttps なのにhttp_proxyなのか?というのもありますが、これもコードを見ると、http_proxyが指定してあればNuGet.Clientがその値を読み取ってそのプロキシサーバーをNuGetの通信ではhttpsでも使うように設定しています。

さて、https_proxy でNuGetのリポジトリを検索してもなにもヒットしません。この環境変数を読み取ることはしていないようです。しかし、https_proxyもしくはHTTPS_PROXYに値をセットするとdotnet restoreのときに使われます。しかもhttp_proxyとは違って不正なURLの場合も使われて、その結果URLにアクセスできない場合はエラーになります。これはなぜ起きるかというと、NuGet.Core がHTTP通信に使っている System.Net.HttpがUnixプラットフォームではcurlライブラリに処理を委譲しているからのようです。

corefx/src/System.Net.Http/src/System/Net/Http/Unix at master · dotnet/corefx · GitHub

さきほどの curl のmanの続きにhttps_proxyもあって、これは大文字小文字を区別しないので、どちらを設定しても使われる挙動になっていました。

なんというかわかりづらい挙動で、はまると抜け出すのが面倒な気がするのでどこかに書いてあると便利な気がするんですが、どこがいいんだろうと悩んでいるところです。

追記: よく見たら、NuGet.configのドキュメントに大文字環境変数で動くと書いていたのでPRを出しました。

*1:確認できないけど多分Macも

*2:正確には環境変数で大文字小文字を区別しないプラットフォーム

.NET Core on Linux の今年をふりかえってみる

.NET Core C#

.NET Core Advent Calendar 3日目です。

qiita.com

昨日のPowerShell on Linux に続いて、.NET Core on Linux (特に.NET Core on RHEL)の現状を、アプリをどうやって開発するのか?に焦点を置いて軽くふりかえってみたいと思います。

.NET Core のリリースとインストール

.NET Core は今年の6月に正式版がリリースされたのですが、.NET Core 本体は正式リリースであるものの、ビルドまわりを含めたtoolingはpreview状態です。そのため、先日リリースされたのは.NET Core 1.1ですが、ビルドツールとしてMSBuildが採用されているバージョンは.NET Core 1.0 preview 3という扱いでリリースされています。.NET Standard 2.0 への移行含めてまだまだ落ち着かない状態はつづきそうです。

blogs.msdn.microsoft.com

もう一つ注意点というか、配布されるタイミングの違いですが、ほとんどのOS向けの.NET Core SDKのリリースはMicrosoftが行っています。インストール手順としてはここにあるドキュメントの通りで、パッケージもMicrosoftが公開されているはずです。

.NET Core Downloads

ですが、RHEL向けのバイナリについては、特にRed Hatがサポート対象としているものについてはRed Hat が公開しています。そのため、公開のタイミングもずれています。実際、.NET Core 1.1はConnect(); 2016のタイミングでしたが、RHEL向けのバイナリは11/29にリリースされました。

またサポートについても違いがあります。.NET Core 一般のサポートはこのページから飛べますが、Microsoft Support Professionalにインシデントを作成してサポートを受けることになります。ちなみに特にWindows上に限ると書いていないのですが、他のOS上のトラブルでも対応してもらえるのかが気になるところです。

.NET Platform Support

.NET Core on RHELのサポートはRed Hat経由になります。開発者向けには、RHELのOS Subscriptionも含む開発者向けプログラムが用意されており無料で使うことができます。

developers.redhat.com

.NET Core on Linuxでの開発

じゃあ、実際アプリを開発するとどうなるのかという話に移ります。といっても、私は仕事上、実際に運用するアプリを作っているわけではなく、新機能の検証とか、Red Hatの製品の機能との組み合わせを確かめるためにアプリを作った範囲での話になります。

なんといってもどのツール(IDE/テキストエディタ)で開発するか、ですがVisual Studio Code一択かなあという気がしています。もちろんvimやemacsを使いなれた人であれば使いなれた環境で.NET Coreアプリを開発するのもありかもしれません。ただ、私が一般的に「.NET Core アプリをLinuxで開発するには、どのツールがよいですか」と聞かれたら「Visual Studio Codeです」と答えます。Jetbrainsが出したRiderですがEAPになって改めて試してみましたが、編集中にフリーズしたりしてちょっとサンプルアプリレベルでも作るのはつらいかなあという印象です。機能自体はVisual Studio Codeより多そうですが、おすすめするためにはもう少ししてから調べ直したいなと思っています。

では、Visual Studio Code を使えば快適化と言われると、さすがにVisual StudioでC#アプリを開発していた時と比べる明らかに使い勝手は落ちます。実際つらいと感じた具体的なポイントは

  • 新しいアイテムの追加がないので、クラスファイル1つ追加するのも、空ファイルを追加してから自分でコードを書く必要がある
  • NuGet パッケージマネジャーのGUIがない。CUIもnuget.exe相当のものはなく、dotnet コマンド経由のもののみ。
  • Razor Viewの補完が聞かない
  • Roslyn SDKのAnalyzer+Code Fixがリアルタイムで動かない (コンパイル時検出+コードFixはできない)

といったあたりでしょうか。いくつか今後のリリースでの対応が予定さているものもありますが、このあたりの機能強化を考えたときに面倒なのは、.NET Core CLIに追加すべき機能なのか、Visual Studio Code (より正確にはそのC#拡張)に追加すべきなのか、NuGetに追加すべきなのか、といったところを切り分けてからそれぞれにフィードバックしないと、フィードバックしてもあまりよい反応がないということです。今年は最初のリリースということで、来年はtoolingもGAになるはずなので、このあたりの機能強化も期待したいところです。

Windowsで開発、Linuxで運用

上の説ではあくまでLinuxで開発するという視点だったのですが、開発マシンはWindowsで、Linux Server上で運用する、というユースケースがあるかもしれません。そのケースにおいては、ぜひともVisual Studioでの開発をおすすめします。.NET Coreアプリは、WindowsでビルドしたバイナリでもそのままコピーするだけでLinux上で動きます*1。また、Visual StudioからLinuxサーバー上で動く.NET Coreプロセスをリモートデバッグすることもできます。これについては、Visual Studio Tools for Docker *2で実現できているため、Docker on WindowsやAzure Container Service固有の技術だと思われるかもしれませんが、違います。あくまで標準の技術として開発されているので、技術的には、任意のLinux (あるいはMacOSX)上へ、任意のDocker ホストへ、そして、Red Hat OpenShift や他のContainer Platform へもデプロイ&デバッグができます。ただ、必要なコマンドやそのオプションが接続先によって異るので、Visual Studio Tools for DockerやVS本体の機能だけでは使うことができません。このあたりは使い易い形での手順がまとまったら、ブログとかに書いていきたいと思っています。

まとめ

という感じで、まとめると、.NET Core on Linux の現状はできるようになった、けどもっと使いやすくできる、という状態な気がします。まだMSBuild+csprojへの移行もありますし、引き続き情報発信していこうと思っています。また、使い易くするためのVisual Studio 拡張やVisual Studio Code拡張のアイディアもあるので、その辺も作っていきたいところです。また、.NET Core on Linuxでこういうことしたいけど、といったご相談もいただければと思います。

*1:アプリモデルにより、プロジェクトやビルド時の設定は必要

*2:Visual Studio 2017からはVS本体に取り込まれる予定

PowerShell on Linux ふりかえり

.NET Core PowerShell

PowerShell Advent Calendar 2日目のエントリです。

qiita.com

今年は.NET Core on RHELを追っかけた一年だったので、その関連でPowerShell on Linuxの現状というか簡単な振り返りをしてみたいと思います。事の始まりはPowerShell のOSS化とLinuxへの対応が発表されたこのブログでした。

blogs.msdn.microsoft.com

PowerShell v6 のα版というステータスでLinuxを含め各種OS向けのバイナリが1月に1回くらいのペースでリリースされています。

github.com

今のところ、CentOS系はrpmをダウンロードしてyum installを実行する形式になっています。CentOS系だからFedoraでもいけるのでは...?とも思われますが、内部で参照している.NET Coreのランタイムが古いせいか、Preview版のFedora24向け.NET Coreをインストールしていても、powershellは起動に失敗します。

$ powershell 
Failed to initialize CoreCLR, HRESULT: 0x80131500

ということなので、CentOS系ではCentOSもしくはRHELで楽しみましょう。さて、LinuxのShell上でpowershellコマンドを実行するとPowerShellのShellに変わりますが、これがなかなか補完が効いたり、色がついたりして使い勝手がよいです*1

これは最後の$_.の間で補完候補を表示した結果です。 f:id:tanaka733:20161201224736p:plain

シンタックスハイライトの様子。 f:id:tanaka733:20161201224932p:plain f:id:tanaka733:20161201225130p:plain f:id:tanaka733:20161201233328p:plain

さて、現状PowerShell v6のαで使えるコマンドは350個ほどしかなく、モジュールを追加したいところですが、そこにも問題があります。

PS /root> @(Get-Command).Count                                                                                                 
349

既存のモジュールの中にはC#などで書いたコードをコンパイルしたdllを参照しているものもありますが、.NET Framework版でビルドしたdllはWindows版でしか動きません。その一つがAzure PowerShellになります。こちらは、PowerShell on Linuxが公開されてかなり早い段階で.NET Core版のバイナリもPreview扱いでリリースしましたが、まだPreview扱いのままのようです... tech.tanaka733.net

さて、PowerShell on Linuxの今後ですが、まだすぐに普及するというステータスではないように思われます。コマンドなりモジュールがLinuxのコマンドにも対応してくれるとうれしいですね。なんといってもPowerShellのメリットはオブジェクトの集合がパイプで流れてきて、オブジェクトのまま*2処理できることにあると思っているので、Linuxの管理系コマンドの結果がオブジェクトでとれると使い勝手もよくなります。

また、DSCの動向ですが、例えば、Azure上でLinuxを動かす場合、Azure VMやVNETまわりのリソースはARMテンプレートで管理し、起動したLinuxより上のレイヤー(OSインストール後の設定、ミドルウェア製品のインストールやセットアップ)はAnsibleで行うというのが一つの形としてあります。例えばLinux中心の環境で一部Windows Serverを動かしたいとなれば、AnsibleでWindowsを管理しAnsibleの標準コマンドで管理しづらいようなWindowsの機能はPowerShell DSCでセットアップするということが考えられます。一方、Windows中心の環境で一部Linuxを使いたいとなれば、PowerShell DSC中心に置いて、PowerShell DSC for LinuxでLinuxを管理する方法がとれるかもしれません。AnsibleのModuleをPowerShell DSCから呼び出すという試みをしている人もいるので、この辺は何がメジャーになるのかまだわからないなあという感想を持っています。

github.com

なにはともあれ、なかなか面白いものが出て来たので、来年も引き続きさわっていきたいと期待している、というのが個人の感想です。

*1:普通のLinuxのコマンドと比べてどうかといわれると微妙だが、補完のきかないdotnetやいまいちなazure cliにくらべるとかなりよい

*2:単なる文字列ではなくという意味