銀の光と碧い空

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

Linux でも C# 7 を使いたい

C# Advent Calendar 10日目の記事です。

qiita.com

C# 7のリリースが近づいてきている(はず)のですが、専らC# 7の記事はVisual Studioで試しましたというのが多く、.NET Core on Linuxでは試せないのか?という疑問がありました。現時点では、.NET Core 1.0 previewとVisual Studio Code の最新版を使えばC# 7の機能を試すことができます。今回は、.NET Core SDK のDaily Build版とVS Code 1.8.0-insider+C#拡張の最新版1.5.3で試しました。

github.com

marketplace.visualstudio.com

$ dotnet --info
.NET Command Line Tools (1.0.0-preview5-004232)

Product Information:
 Version:            1.0.0-preview5-004232
 Commit SHA-1 hash:  355b6233cb

Runtime Environment:
 OS Name:     rhel
 OS Version:  7.3
 OS Platform: Linux
 RID:         rhel.7.2-x64
 Base Path:   /opt/dotnet/sdk/1.0.0-preview5-004232
続きを読む

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

微妙にハマったので、書いておきます。.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 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本体に取り込まれる予定