« 2016年07月 | メイン

1

2017年02月 記事一覧

2017年02月16日

さくらインターネット共有サーバーへの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を打ってネットワーク接続が正常かチェック。
# ping google.com
次にportsの取得。bootstrapは必要ないかも?
# portsnap fetch
# portsnap extract
# pkg bootstrap
portsの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用の該当パッケージをダウンロードして、さくらレンタルサーバーへアップロードします。
http://pkg.freebsd.org/FreeBSD:11:amd64/latest/All/

http://pkg.freebsd.org/FreeBSD:11:amd64/latest/All/glib-2.46.2_4.txz
http://pkg.freebsd.org/FreeBSD:11:amd64/latest/All/indexinfo-0.2.6.txz
http://pkg.freebsd.org/FreeBSD:11:amd64/latest/All/libffi-3.2.1.txz
http://pkg.freebsd.org/FreeBSD:11:amd64/latest/All/libinotify-20160505.txz
http://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にアクセス。
http://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#利用が可能になり、(容易に)実現できる幅が広がりました。
これは残っている問題点を吹き飛ばすほどに大きなメリットです。

1





usefullcode@gmail.com

About 2017年02月

2017年02月にブログ「UsefullCode.net」に投稿されたすべてのエントリーです。

前の記事は2016年07月です。

他にも多くのエントリーがあります。メインページ記事一覧も見てください。