Ubuntu 12.04.3 LTS に Katana(OwinHost.exe) をインストールする
OwinHost.exe - Katana
C#+Owinのコード書きたい。でも、IISじゃなくてLinuxでホストしたいよっていうヒネクレな状況で、とりあえず、Katanaが動かないと話にならないので、Katanaを動かしてみたっていうのが趣旨です。
Mono 3.X
とりあえず、新しいバージョンのMonoじゃないとOwinHostが動かないと思うんだけど、Ubuntu 12.04.3には、mono 2.Xのmonoしか入ってない。というか、gmcsな時点でアウト。
apt-cacheでパッケージを確認した感じではやっぱり、C# 3.0までしか対応してない。悲しい。
espresso3389@nu:~/katana$ apt-cache show mono-gmcs Package: mono-gmcs Priority: optional Section: cli-mono Installed-Size: 1178 Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com> Original-Maintainer: Debian Mono Group <pkg-mono-group@lists.alioth.debian.org> Architecture: all Source: mono Version: 2.10.8.1-1ubuntu2.2 Replaces: mono-devel (<< 2.4.2.3), mono-mcs (>= 1.1.10), mono-mcs (<= 1.1.13) Depends: mono-runtime (>= 1.1.8.1), libc6 (>= 2.15) | libc6.1 (>= 2.15) | libc0.1 (>= 2.15), libmono-corlib2.0-cil (>= 2.10.8.1), libmono-system2.0-cil (>= 2.10.3), libmono-corlib2.0-cil (<< 2.10.8.2) Recommends: pkg-config Filename: pool/main/m/mono/mono-gmcs_2.10.8.1-1ubuntu2.2_all.deb Size: 422312 MD5sum: ef7aed6da981daf02fb910147b4b105e SHA1: 1de52356da26cb060cebd78c24849f4b356bd8db SHA256: 3164fdd32843326be71ad8e34f0d780b55c10b77cd74d919fff746dc0d5a412b Description-en: Mono C# 2.0 and C# 3.0 compiler for CLI 2.0 This is the Mono C# (C-Sharp) 2.0 and C# 3.0 compiler, a platform-independent compiler which produces CIL (Common Intermediate Language) binary executables. The gmcs compiler supports two different featuresets (C# versions). ....
directhex/monoxide
ソースからビルドするほど若くないので、そうじゃない方法を探したところ、 directhex さんという人が directhex/monoxide という吸ったら死にそうな感じの危険なパッケージ群をホストしてくれているらしい。
Installing Mono 3.x (3.0.x and/or 3.2.x) - stackoverflow
stackoverflowからそのまま引用すると、やることは簡単で、
espresso3389@nu:~/katana$ sudo add-apt-repository ppa:directhex/monoxide
とやって、このレポジトリを追加するだけ。ただし、この見慣れない、 add-apt-repository というツールは、標準では入ってないらしい。sudoなしでタイプしてみたところ、
espresso3389@nu:~/katana$ add-apt-repository The program 'add-apt-repository' is currently not installed. You can install it by typing: sudo apt-get install python-software-properties
と出てきたので、
espresso3389@nu:~/katana$ sudo apt-get install python-software-properties
してインストールした。もちろん、この後に apt-get update しないと反映されない。ここまでをまとめると、詰まるところ、次の作業をやれと言うこと:
espresso3389@nu:~/katana$ sudo apt-get install python-software-properties espresso3389@nu:~/katana$ sudo add-apt-repository ppa:directhex/monoxide espresso3389@nu:~/katana$ sudo apt-get update
ということで、本ちゃんのインストール。フルセットをインストールするために、mono-completeをインストールする。
espresso3389@nu:~/katana$ sudo apt-get install mono-complete
インストールが終わったら、monoのバージョンを確認しておこう。
espresso3389@nu:~/katana$ mcs --version Mono C# compiler version 3.2.1.0
OK。C# 5.0対応(async/await対応)が入っているバージョンだ。これで好き放題出来る。
NuGet を取得する
NuGetとは、.NET向けのパッケージマネージャ。これを使えば、欲しいモジュールを自由自在にインストールできる。
Installing NuGet にある Direct Downloadから、nuget.exeを入手する。
espresso3389@nu:~/katana$ wget http://nuget.org/nuget.exe
そして、どうやら、chmodで実行権限を付けておけば、普通に実行ファイルとして実行できる模様なので、そうしておく(mono経由で実行しなくて良いみたい)。
espresso3389@nu:~/katana$ chmod +x nuget.exe
バージョンを確認してみたところ、今のところ、
espresso3389@nu:~/katana$ ./nuget.exe NuGet Version: 2.7.41115.310 usage: NuGet <command> [args] [options] Type 'NuGet help <command>' for help on a specific command. ...
と表示された。
NuGetのためにSSL証明書をインストールする
How to Use NuGet on Mono, Part I - Half-Blood Programmerにあるように、SSLの証明書をインストールしないと、NuGetがパッケージをダウンロードできないので、そうする。
espresso3389@nu:~/katana$ mozroots --import --sync
Katana (OwinHost)のインストール
ソースからビルドすべきかとも考えたが、やっぱり面倒なので、NuGetでさっくり行きます。-Version 2.0.2は省略しても良いが、その場合、ここの例とはバージョンが変わる可能性がある。
espresso3389@nu:~/katana$ ./nuget.exe install OwinHost -Version 2.0.2 -pre
そうすると、 ./OwinHost.2.0.2/tools/ に
espresso3389@nu:~/katana$ find OwinHost.2.0.2/ OwinHost.2.0.2/ OwinHost.2.0.2/OwinHost.2.0.2.nupkg OwinHost.2.0.2/tools OwinHost.2.0.2/tools/Microsoft.Owin.dll OwinHost.2.0.2/tools/OwinHost.exe.config OwinHost.2.0.2/tools/install.ps1 OwinHost.2.0.2/tools/OwinHost.exe OwinHost.2.0.2/tools/Owin.dll OwinHost.2.0.2/tools/uninstall.ps1 OwinHost.2.0.2/tools/Microsoft.Owin.Host.HttpListener.dll OwinHost.2.0.2/tools/Microsoft.Owin.Hosting.dll
OwinHost.exe も chmod +xしておいた方がイライラが少なくなるかも知れない。
espresso3389@nu:~/katana$ chmod +x OwinHost.2.0.2/tools/OwinHost.exe
実験
さて、せっかくなので、Linux上で何らかのサンプルをビルドしてみましょう。
@miso_soup3さんのブログにKatana で Hello, worldというエントリがあるので、そのコードを拝借。
下記のコードを Startup.cs として保存:
using System; using System.Threading.Tasks; using Microsoft.Owin; using Owin; [assembly: OwinStartup(typeof(WebApplication40.Startup1))] namespace WebApplication40 { public class Startup1 { public void Configuration(IAppBuilder app) { app.Run(context => { context.Response.ContentType = "text/plain"; return context.Response.WriteAsync("Hello World!"); }); } } }
web.config:
<?xml version="1.0" encoding="utf-8"?> <configuration> <appSettings> <add key="owin:AppStartup" value="WebApplication40.Startup1, Startup"/> </appSettings> </configuration>
OwinHost.exeは、 binディレクトリ下のアセンブリしか読み込まないような仕様になっているらしいので、先にbinディレクトリを作成する。
espresso3389@nu:~/katana$ mkdir bin
そして、Startup.csをmcsでDLL(library)としてビルドしてbinに配置するには、次のようにする(デバッグ情報有り/最適化なし):
espresso3389@nu:~/katana$ mcs -debug -optimize- -target:library -lib:./OwinHost.2.0.2/tools/ -r:Microsoft.Owin.dll -r:Owin.dll Startup.cs -out:bin/Startup.dll
今のディレクトリ構造はこの作業の通りになっていれば、
espresso3389@nu:~/katana$ find . . ./nuget.exe ./Startup.cs ./web.config ./OwinHost.2.0.2 ./OwinHost.2.0.2/tools ./OwinHost.2.0.2/tools/Microsoft.Owin.dll ./OwinHost.2.0.2/tools/OwinHost.exe.config ./OwinHost.2.0.2/tools/install.ps1 ./OwinHost.2.0.2/tools/OwinHost.exe ./OwinHost.2.0.2/tools/Owin.dll ./OwinHost.2.0.2/tools/uninstall.ps1 ./OwinHost.2.0.2/tools/Microsoft.Owin.Host.HttpListener.dll ./OwinHost.2.0.2/tools/Microsoft.Owin.Hosting.dll ./OwinHost.2.0.2/OwinHost.2.0.2.nupkg ./OwinHost.2.0.2/ReadMe.txt ./bin ./bin/Startup.dll ./bin/Startup.dll.mdb
となっているはず。この状態で、OwinHost.exeを実行する:
espresso3389@nu:~/katana$ ./OwinHost.2.0.2/tools/OwinHost.exe Starting with the default port: 5000 (http://localhost:5000/) Started successfully Press Enter to exit
何度も言うが、このマシンはヘッドレスなので、ブラウザは動かない。従って、面倒だが、lynxなどで http://localhost:5000 を参照するか、あるいは、OwinHost.exeを起動するときに、-uオプションで、明示的に公開URLを指定する必要がある。
次の例は、 http://192.168.0.18:8080/ で公開する場合:
espresso3389@nu:~/katana$ ./OwinHost.2.0.2/tools/OwinHost.exe -u http://192.168.0.18:8080/
ここにアクセスすれば、
Hello World!
と表示されるはず。
[追記] monodoc-browser のインストール処理中にエラーが発生する
処理中に、次のようなエラーが発生する。
... Setting up monodoc-browser (2.10-2) ... generating monodoc index... grep: /etc/gre.d/*.conf: No such file or directory Unhandled Exception: System.TypeLoadException: Could not load type 'Monodoc.EditMerger' from assembly 'monodoc, Version=1.0.0.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756'. [ERROR] FATAL UNHANDLED EXCEPTION: System.TypeLoadException: Could not load type 'Monodoc.EditMerger' from assembly 'monodoc, Version=1.0.0.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756'. dpkg: error processing monodoc-browser (--configure): subprocess installed post-installation script returned error exit status 1 Errors were encountered while processing: monodoc-browser E: Sub-process /usr/bin/dpkg returned an error code (1) ...
これは、mono-completeをインストールしている性で、monodoc-browserなんていうどうでも良い物がインストールされようとしていて、エラーになっているだけなので、素直に、monodoc-browserだけを消せば良い。
espresso3389@nu:~/katana$ sudo apt-get remove monodoc-browser
[追記] binfmt_misc
monoのバイナリというか、普通のWindowsのexeに実行権限さえ付ければ動作しちゃうのは、binfmt_miscというカーネルのモジュールが有効になっているからです。
日本語のドキュメントだと、「binfmt_misc.txt - いろんな (お好みの) バイナリフォーマットのカーネルサポート v1.1」かな。
要は、ファイルのシグニチャ(ヘッダ)を見て、そのファイルをハンドルするプログラムを特定する仕組みですが、MZっていうシグニチャでPEフォーマットなことは分かるけど、それって、Wineで動かせば良いの?それとも、Mono?みたいな話に関しては、適当なシェルスクリプト等に投げて、そこで、fileコマンドなどを使ってフォーマット判別すると言うことのようです。
とりあえず、/usr/sbin/update-binfmts というコマンドがあって、エントリを見たかったら、--displayというオプションを与えれば良い感じ。
espresso3389@nu:~$ /usr/sbin/update-binfmts --display llvm-3.0.binfmt (enabled): package = llvm type = magic offset = 0 magic = BC mask = interpreter = /usr/bin/lli-3.0 detector = python2.7 (enabled): package = python2.7 type = magic offset = 0 magic = \x03\xf3\x0d\x0a mask = interpreter = /usr/bin/python2.7 detector = cli (enabled): package = mono-runtime type = magic offset = 0 magic = MZ mask = interpreter = /usr/bin/cli detector = /usr/lib/cli/binfmt-detector-cli
おぉ、llvmの中間コードが動くっぽいな。楽しい。