さくらインターネット共有サーバーへのmono C#環境のインストール
さくらのレンタルサーバー スタンダードはそこそこ安くて使えるので2017年2月現在、私は2アカウント契約しています。
しかし残念なことに.NET COREやASP.NET MVCはもちろん、monoすら使えません。
今回はこの共有サーバー上にmonoをインストールします。
少し古い情報ですが、2010年4月15日のさくらインターネット共有サーバーへmonoをインストールする方法 by 骨折飲料@kossetsu_inryoを基に作業しました。
私はlinuxの知識がないのでこれがなければ不可能でした。本当に感謝です。
1.作業用のFreeBSDをダウンロード
ローカルでmonoをビルドするための準備です。
共有サーバーはFreeBSD(x64)で動作しているため、同じくFreeBSD(x64)をローカルに用意します。
今回はミラーサイトからFreeBSD 11.0のisoイメージをダウンロードして作業しました。
ftp://ftp2.jp.freebsd.org/pub/FreeBSD/releases/ISO-IMAGES/11.0/FreeBSD-11.0-RELEASE-amd64-dvd1.iso
※本家のftpサーバーは転送が遅いです
※共有サーバーはFreeBSD 9.1です。9.1ではmonoのmake時に「古いFreeBSDはもうサポートしない!」というエラーになるので最新のFreeBSDを利用しました
2.作業用のFreeBSDのインストール
仮想PCを用意してデフォルトの設定のままインストールします。
ネットワーク接続は必須です。
3.monoのビルド
引き続きローカルでの作業です。
FreeBSDのインストールが終わったら、rootでログインします。
# ping google.com次にportsの取得。bootstrapは必要ないかも?
# portsnap fetch # portsnap extract # pkg bootstrapportsのmonoフォルダへ移動してビルド。そしてテストインストール/アンインストール。
# cd /usr/ports/lang/mono # make # make install # make deinstall※make中にはGUIで何回か選択を迫られますがすべてデフォルトでOK ※monoの公式サイトからgit cloneでソースを持ってきてビルドしたくなりますが、それはNG。必ずportsを使います
4.monoパッケージの作成とアップロード
引き続きローカルでの作業です。
まずはローカルにレンタルサーバーと同じ名前のhomeフォルダを用意して、リンクを作成。# mkdir -p /home/hoge123456789123hoge # ln -s /usr/local /home/hoge123456789123hoge/localそしてmakeとパッケージ作成
# setenv FORCE_PKG_REGISTER yes # make LOCALBASE=/home/hoge123456789123hoge/local # make LOCALBASE=/home/hoge123456789123hoge/local packageもうリンクは要らないので解除。
# unlink /home/hoge123456789123hoge/localカレントフォルダにmonoのパッケージが作成されているので、lsでそれを確認。
# lsできたパッケージをレンタルサーバーへアップロード。
# sftp hoge123456789123hoge@hoge123456789123hoge.sakura.ne.jp > put mono-4.6.2.7.txz > quitローカルのFreeBSDでの作業はこれで終わりです。
※「hoge123456789123hoge」はさくらのレンタルサーバーのアカウントに合わせて置換してください
※FORCE_PKG_REGISTERを定義しないと、pkg-1.9.4_1がすでにあると言われてmakeが止まる
5.monoパッケージのインストール
レンタルサーバー上での作業です。
さくらレンタルサーバーへSSHでログインします。 そしてアップロードしたmonoのパッケージを解凍して/home/hoge123456789123hoge/local内に移動します。% xz -dc mono-4.6.2.7.txz | tar xfv - % mv home/hoge123456789123hoge/local .カレントフォルダに残ったゴミを削除。
% rm -R home % rm +COMPACT_MANIFEST % rm +MANIFEST※pkg_addが出来ればいいのですが、+CONTENTSがないと怒られてできないので普通に解凍して移動という形でインストールします インストールできたので実際にmonoを実行してみます。
% setenv LD_LIBRARY_PATH /home/hoge123456789123hoge/local/lib % setenv PATH ${PATH}:/home/hoge123456789123hoge/local/bin % mono -V...「Shared object "libinotify.so.0" not found, required by "mono"」と怒られて実行できませんでした。 依存しているパッケージがないようです。
6.mono依存関係の調査と依存パッケージのダウンロード
一部、レンタルサーバーでの作業です。
まずはmonoの依存関係をFreeBSD公式サイトで調べます。
monoは/usr/ports/lang/monoなのでカテゴリにlang指定で検索するだけです。
https://www.freebsd.org/cgi/ports.cgi?query=mono&stype=name&sektion=lang
mono-4.6.2.7 Open source implementation of .NET Development Framework Long description : Changes Maintained by: mono@FreeBSD.org Requires: bash-4.4.5, bison-2.7.1_1,1, expat-2.2.0_1, gettext-runtime-0.19.8.1_1, gettext-tools-0.19.8.1, glib-2.46.2_4, gmake-4.2.1_1, indexinfo-0.2.6, libffi-3.2.1, libiconv-1.14_10, libinotify-20160505, m4-1.4.17_1,1, p5-XML-Parser-2.44, pcre-8.39_1, perl5-5.24.1.r4_1, python27-2.7.13_1, readline-6.3.8レンタルサーバー内でlsをしてインストール状況を調べるとこのような感じでした。
bash-4.4.5 インストール済みバージョン4.3.30 bison-2.7.1_1,1 expat-2.2.0_1 インストール済みバージョン不明libexpatあり gettext-runtime-0.19.8.1_1 インストール済みバージョン0.18.1 gettext-tools-0.19.8.1 glib-2.46.2_4 gmake-4.2.1_1 インストール済みバージョン3.82 indexinfo-0.2.6 libffi-3.2.1 libiconv-1.14_10 インストール済みバージョン不明 libinotify-20160505 m4-1.4.17_1,1 インストール済みバージョン不明 p5-XML-Parser-2.44 pcre-8.39_1 インストール済みバージョン不明libpcreあり perl5-5.24.1.r4_1 インストール済みバージョン5.14.4 python27-2.7.13_1 インストール済みバージョン2.7.6 readline-6.3.8 インストール済みバージョン不明libreadlineあり
FreeBSDの公式サイトからamd64用の該当パッケージをダウンロードして、さくらレンタルサーバーへアップロードします。
https://pkg.freebsd.org/FreeBSD:11:amd64/latest/All/
https://pkg.freebsd.org/FreeBSD:11:amd64/latest/All/glib-2.46.2_4.txz
https://pkg.freebsd.org/FreeBSD:11:amd64/latest/All/indexinfo-0.2.6.txz
https://pkg.freebsd.org/FreeBSD:11:amd64/latest/All/libffi-3.2.1.txz
https://pkg.freebsd.org/FreeBSD:11:amd64/latest/All/libinotify-20160505.txz
https://pkg.freebsd.org/FreeBSD:11:amd64/latest/All/p5-XML-Parser-2.44.txz
※bisonやそのほかのバージョン不明品は問題が発覚するまで放置です
7.依存パッケージのインストール
レンタルサーバー上での作業です。
さくらレンタルサーバーへSSHでログインします。 そしてアップロードした依存パッケージを解凍して/home/hoge123456789123hoge/local内に移動します。% xz -dc glib-2.46.2_4.txz | tar xfv - % xz -dc indexinfo-0.2.6.txz | tar xfv - % xz -dc libffi-3.2.1.txz | tar xfv - % xz -dc libinotify-20160505.txz | tar xfv - % xz -dc p5-XML-Parser-2.44.txz | tar xfv - % cp -a usr/* .カレントフォルダに残ったゴミを削除。
% rm +COMPACT_MANIFEST % rm +MANIFEST※usrフォルダはリンクもあるのでFTPクライアントで削除しました・・・
8.monoの動作確認
引き続きレンタルサーバー上での作業です。
依存パッケージもインストールできたので実際にmonoを実行してみます。% setenv LD_LIBRARY_PATH /home/hoge123456789123hoge/local/lib % setenv PATH ${PATH}:/home/hoge123456789123hoge/local/bin % mono -V
Mono JIT compiler version 4.6.2 (Stable 4.6.2.7/08fd525 Thu Feb 16 06:14:58 UTC 2017) Copyright (C) 2002-2014 Novell, Inc, Xamarin Inc and Contributors. www.mono-project.com TLS: __thread SIGSEGV: altstack Notification: kqueue Architecture: amd64 Disabled: none Misc: softdebug LLVM: supported, not enabled. GC: sgen
OK!monoが共有サーバー上で動作しているように見えます。
さらにtest.csというファイル名で以下のソースコードをアップロード。using System; public class HelloWorld { static public void Main () { Console.WriteLine ("Hello Mono World"); } }ビルドして実行できるか確認。
% mcs test.cs % mono test.exe
9.mono C#をCGIとして動かしてみる
一部レンタルサーバー上での作業です。
さすがに共有サーバーでASP.NETみたいなことは無理(だと思う)ので古典的なCGIとしてmonoを実行させてみます。
※調べたらfastcgiとxpsの組み合わせでASP.NETも共有サーバーで動かせそうでした
今回はexeを外部コマンドとして呼び出すだけのperlスクリプトを用意し、それをcgiとして読み込ませる形にしました。
まずはソースコードをtest.csとして保存。using System; public class HelloWorld { static public void Main () { Console.WriteLine("Content-Type: text/html\n"); Console.WriteLine("<html>"); Console.WriteLine("<body>"); Console.WriteLine("<H1>test mono CGI!</H1>"); Console.WriteLine("</body>"); Console.WriteLine("</html>"); } }ビルドしてtest.exeを生成します。
% mcs test.cs次にperlスクリプトをtest.cgiとしてwwwフォルダ内に保存。実行属性を付ける。
#!/usr/local/bin/perl -w $ENV{"HOME_DIR"} = "/home/hoge123456789123hoge"; $ENV{"PATH"} = $ENV{"HOME_DIR"} . "/local/bin:" . $ENV{"PATH"}; $ENV{"TMP"} = $ENV{"HOME_DIR"} . "/tmp"; $ENV{"PKG_DIR"} = $ENV{"HOME_DIR"} . "/local"; $ENV{"PKG_CONFIG_PATH"} = $ENV{"PKG_DIR"} . "/libdata/pkgconfig"; $ENV{"LD_LIBRARY_PATH"} = $ENV{"PKG_DIR"} . "/lib"; $ENV{"LD_RUN_PATH"} = $ENV{"LD_LIBRARY_PATH"}; $ENV{"MONO_HOME"} = $ENV{"PKG_DIR"}; $ENV{"MONO_FRAMEWORK_PATH"} = $ENV{"MONO_HOME"}; $ENV{"MONO_CFG_DIR"} = $ENV{"MONO_HOME"} . "/etc"; $ENV{"MONO_CONFIG"} = $ENV{"MONO_HOME"} . "/etc/mono/mconfig"; $ENV{"MONO_GAC_PREFIX"} = $ENV{"MONO_HOME"}; $ENV{"MONO_PATH"} = $ENV{"MONO_HOME"} . "/lib/mono"; $ENV{"MONO_MANAGED_WATCHER"} = "false"; $ENV{"MONO_SHARED_DIR"} = $ENV{"HOME_DIR"} . "/tmp"; $ENV{"C_INCLUDE_PATH"} = $ENV{"PKG_DIR"} . "/include"; $ENV{"XDG_DATA_HOME"} = $ENV{"MONO_HOME"} . "/share"; system('mono /home/hoge123456789123hoge/tmp/test.exe');ブラウザーを開いてCGIにアクセス。
https://hoge123456789123hoge.sakura.ne.jp/test.cgiこれでメッセージが表示されれば成功です。 perlではなくshを使って、さらにエラーログ出力を追加し環境変数書くのが面倒だったので省いたcgiスクリプトにするならこんな感じ。
#!/bin/sh exec 2>>/home/hoge123456789123hoge/tmp/mono_cgi.err exec env \ PATH="/home/hoge123456789123hoge/local/bin:$PATH" \ LD_LIBRARY_PATH="/home/hoge123456789123hoge/local/lib:$LD_LIBRARY_PATH" \ TMP="/home/hoge123456789123hoge/tmp" \ MONO_SHARED_DIR="/home/hoge123456789123hoge/tmp" \ mono /home/hoge123456789123hoge/tmp/test.exe
ここまで動けばpost/getデータを Console.OpenStandardInput() や Environment.GetEnvironmentVariable() で処理するルーチンさえC#で用意すればどのようなものでも作れます。
さらに簡易的なリモートデバッグであればVisual Studio 2015にMonoRemoteDebuggerのextensionをインストールすればできます。
しかしまともなリモートデバッグははたして可能なのか?という大問題もありますし、そのほかにもcgiをいちいち手動で処理することになるのでそれなりに小さな問題が思いつきます。
しかし今まで無理だったレンタルサーバー上でのC#利用が可能になり、(容易に)実現できる幅が広がりました。
これは残っている問題点を吹き飛ばすほどに大きなメリットです。