Linuxサーバー構築~その3~

<はじめに>
Linuxサーバー構築シリーズその3です。

Linuxサーバー構築シリーズその2の訂正
・ghcはyumでインストールせずに、ghc7.6.3とhaslkell-platformを
 ソースからインストールします。
httpdをyumでインストールしました。
 configの設定は次回以降で書きます。

<実施内容>
さて、今回はghcとhaskell-platformをインストールします。

haskell-platformにはghcが含まれるようなのですが…

とりあえず、先にインストールを試みます。

// ダウンロード
sudo wget http://www.haskell.org/platform/download/2013.2.0.0/haskell-platform-2013.2.0.0.tar.gz

// チェックサムの確認
sha1sum haskell-platform-2013.2.0.0.tar.gz

// 展開
tar xvzf haskell-platform-2013.2.0.0.tar.gz

と、ここでREADMEの中を見てみると…

f:id:nomurabbit:20131211233312p:plain

どうもghc7.6.3が必要みたいですね。

そこで、ghcのダウンロードサイトを確認すると

最新版(2013年12月11日時点)が7.6.3でしたので、これをインストールします。

// ダウンロード
sudo wget http://www.haskell.org/ghc/dist/7.6.3/ghc-7.6.3-x86_64-unknown-linux.tar.bz2

// 展開
tar xvfj haskell-platform-2013.2.0.0.tar.gz

// .configureの実行
./configure --prefix=/usr/local/haskell/ghc/7.6.3

// インストール
sudo make install

これで、ghcのインストールは無事に完了したはずです。

いざ、haskell-platformのインストール!…と、いきたいことろですが

このままだとgmplibが無えよ!って怒られます。

さらにzlibも無えよ!って怒られます。

ついでにOpenGLのライブラリが無えよ!とも怒られるみたいです。

それらのライブラリをインストールします。

// gmpのインストール
sudo wget https://ftp.gnu.org/gnu/gmp/gmp-5.1.3.tar.bz2

tar xjvf gmp-5.1.3.tar.bz2

./configure

make

make check

sudo make install

// /etc/ld.so.confの編集
>include ld.so.conf.d/*.conf
>
>/usr/lib
>/usr/local/lib

sudo ldconfig

// zlibのインストール
sudo wget http://zlib.net/zlib-1.2.8.tar.gz

tar zxvf zlib-1.2.8.tar.gz

./configure

make

sudo make install

// freeglut-develのインストール
sudo yum -y install freeglut-devel

これでようやくhaskell-platformがインストールできます。

// haskell-platformのインストール
./configure --prefix=/usr/local/haskell/haskell-platform/2013.2.0.0

make 

sudo make install

// cabalのupdateもしておきます
cabal update

<まとめ>
今回でghcが使えるようになりました。

次回はiptablesやApacheのあたりを設定していく予定です。

<参考>
http://takuya71.hatenablog.com/entry/2013/02/04/000022

http://neetmenblog.blog116.fc2.com/blog-entry-9.html

Linuxサーバー構築~その2~

<はじめに>
Linuxサーバー構築シリーズその2です。

前回その1ではOSのインストールやNICの有効化を実施しました。

今回はyumリポジトリの確認とSSH公開鍵の作成、

さらに起動プロセスの確認を行います。


<実施内容>
yumリポジトリの確認

/etc/yum.repo.d/CentOS-Base.repoの内容を編集します。

[base],[updates],[extras],[centosplus],[contlib]の値について

初期値はbaseurlがコメントアウトされているので、

理研のurlに変更してコメントアウトを解除します。

編集内容を保存してyum updateを実施します。

yumのログは/var/log/yum.log に出力されるので中身も確認すると、

先ほどアップデートしたパッケージのログが確認できます。


ssh公開鍵の作成

CentOS 6.4をインストールするとsshが最初からインストールされていて

OS起動時にsshdも起動しています。

また、iptablesを確認すると22番ポートも開いています。

このままでもユーザーとパスワードでならばログインすることも可能ですが、

今回のサーバーはアクセスするクライアントが固定なので公開鍵を使用します。

作成した公開鍵を下記のファイル名で保存します。

~/.ssh/authorized_keys

この時.sshフォルダの属性を700に、

authorized_keysファイルの属性を600に変更しておきます。

公開鍵を利用してアクセスできることが確認できたら

パスワードによるアクセスを制限します。

/etc/ssh/sshd_configファイルのパスワード認証をnoに変更し、

f:id:nomurabbit:20131208204300p:plain

その後、sshdを再起動します。


□起動プロセスの確認

起動プロセスはps axで確認します。

また、LISTEN状態のポートをnetstatで、

さらに外部からのポートの状態をnmapで確認します。

※どのプロセスがどのポートを使用しているかについては

lsofコマンドで詳細が見えるようです。

netstatで確認すると、22番ポートと25番ポートがLISTEN状態でした。

f:id:nomurabbit:20131208205233p:plain

22番ポートはsshにしても、25番ポートははSMTP

心当たりがないのでyumでインストールしたlsofコマンドで確認してみると

f:id:nomurabbit:20131208210525p:plain

やはり、smtpでLISTENされているみたいです。

そこで、runlevelとchkconfigを確認してみると、

f:id:nomurabbit:20131208210926p:plain

f:id:nomurabbit:20131208210934p:plain

いました!postfixがrunlevel3でonになっているようです。

不要なので下記のコマンドで切っておきます。

chkconfig --level 23 postfix off

最後にnmapで確認すると、22番ポートだけが空いています。

f:id:nomurabbit:20131208212722p:plain


□必要なパッケージのインストール

本題からは外れますが、下記のパッケージをインストールしておきます。

バージョンは特にこだわらないのでパッケージの管理はyumに任せます。

・nslookup
・traceroute
gcc
・make
・cpp
ghc(12/11削除)
perl
httpd(12/11追加)
・rpcbind(14/08/16追加)
vim(14/08/16追加)
・lsof(14/08/16追加)
・ntp(14/08/16追加)

※nslookupはbind-utilsパッケージに含まれます。

<まとめ>
今回までの作業で、sshでつなげて、yumが使えるようになりました。

また、余分なプロセスを切ることができました。

次回はWebサーバーをインストールしてCGIを作成してみることにします。

Linuxサーバー構築~その1~

<はじめに>
Linuxでサーバー構築を行う様を記録していきます。

下記の4つの役割を実装することを目標にすすめます。
・ドメインコントローラー
・ファイルサーバー
DNSサーバー
・バージョン管理サーバー


<作業内容>
まずはOSのインストールを行います。

今回構築するのはCentOS6.4です。

最終的にはHP ProLiant MicroServerに構築しますが、

今回は検証も兼ねてWindows7上のVirtualBoxにインストールします。

インストールの時に注意するのは2点です。


□ネットワークの詳細

f:id:nomurabbit:20131207010749p:plain

上の画像の「自動接続する」のチェックはデフォルトで入っていません。

このチェックが入っていないとOS起動後に手動でNICを有効にしないといけません。


□パーティションの分割

f:id:nomurabbit:20131207012044p:plain

今回は上の画像のように分割しました。

ファイルサーバーの割に /home が少ないのは

ホストOSのHDDの空き容量がわずかな故です。 ^^;

実際このあたりは自由に分割しちゃっていいと思います。

注意点として、基本パーティションは最大4つまでしか分割できません。

/ や 特に /boot なんかは基本パーティションに割り当てないといけません。

/home や /var なんかは拡張パーティションに割り当ててもおkです。


引き続きMinimalでインストールを続けて、

必要なものは随時インストールすることにします。


OSのインストールが無事に済んだら作業用のユーザーを作ります。

コマンドは下記。

# adduser <ユーザー名>
# passwd <ユーザー名>

本来ならこの時点でグループも決めた方がいいかもしれません。

今のところユーザーはroot、作業用、ファイルサーバー用の3つなので、

グループはスルーして進めます。

次に作業用のユーザーにsudo権限を付与します。

# visudo
//------------------------------------------------------
/etc/sudoers

# Arrows root to run any commands anywhere
<ユーザー名> ALL=(ALL) ALL // 追加
//------------------------------------------------------

これで、先ほど作ったユーザーで sudo コマンドが利用できるようになります。


さて、インストールの際にネットワークの自動接続に

チェックをしなかった場合はNICを有効にしないといけません。

まずは設定ファイルを編集します。

//------------------------------------------------------
/etc/sysconfig/network-scripts/ifcfg-eth0

DEVICE=eth0
HWADDR=FF:FF:FF:FF:FF:FF
TYPE=Ethernet
UUID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
ONBOOT=yes // ここをyesにすることで、起動時にNICが有効になるようです。
NM_CONTROLLED=yes
BOOTPROTO=static
IPADDR=xxx.xxx.xxx.xxx // IPアドレスを指定します。
NETMASK=xxx.xxx.xxx.xxx // サブネットマスクを指定します。
GATEWAY=xxx.xxx.xxx.xxx // ゲートウェイを指定します。
//------------------------------------------------------

次にNICを有効にします。

#ifdown eth0 // eth0の無効化
#ifup eth0 // eth0の有効化

ついでにDNSサーバーも指定します。

//------------------------------------------------------
/etc/resolv.conf

nameserver xxx.xxx.xxx.xxx
//------------------------------------------------------


一通り設定し終わったら確認です。

ネットワークの設定は下記のコマンドで確認します。

#ifconfig // ネットワークの情報

#nslookup // DNSサーバーの情報

#traceroute // ルーティングの情報

#tracepath // ルーティングの情報

この時点ではnslookupとtracerouteはインストールされていないので、

後ほどパッケージをインストールしたときに確認します。


<まとめ>
この回ではOSのインストールとユーザーの作成、ネットワークの設定を実施しました。

次回はyumのリポジトリと浮いてるプロセスなんかを確認します。

また、次回以降必要なパッケージやサーバーをインストールしていきます。

F# で Oracle にアクセスしてみたよ!

<はじめに>
この記事は F# Advent Calendar 2013 7日目の記事です。

6日目は@masaru_b_clさんの F# InteractiveをConEmu上で利用する でした。

さて、F#を勉強し始めて、プライベートでちょいちょい書いていると、

「そのうち業務でもF#使いたいなー?」なんて妄想したりしますよね?

いざF#を業務に導入するとなると、

きっと既存の情報資産を活用できて、かつインパクトが少ない

例えば小規模なマスタメンテ用のWebサービスの作成ぐらいから

始めていくのが現実的かなー?なんて思ったりします。

今回はそんな来るべき日に備えて、

ADO.NETを使ってF#でOracleにアクセスする方法」

を覚書程度に書いてみました。

<対象データ>
下記のテーブルからデータを取得します。

f:id:nomurabbit:20131201223313p:plain

<プログラム1>
とりあえず、コンソールアプリケーションで単純にOracleからデータを取得してみます。

OracleClientはOracle.DataAccess.Clientを利用します。

open System
open System.Data
open System.Configuration
open Oracle.DataAccess.Client

[<EntryPoint>]
let main(args : string[]) = 

    // 接続文字列の取得
    let conStr = ConfigurationManager.ConnectionStrings.Item "connection"
    let con    = new OracleConnection(conStr.ToString())
    
    // SQLの定義
    let sqlStr = "SELECT * FROM MEMBER WHERE ID = 1"
    let cmd    = new OracleCommand(sqlStr, con)

    con.Open()

    // データの取得
    let reader = cmd.ExecuteReader()
    let result = reader.Read()
    
    // 取得したデータの出力
    printfn "%s %s %s %s" (reader.GetString(0)) (reader.GetString(1)) (reader.GetString(2)) (reader.GetString(3))
    
    reader.Close()
    con.Close()
    
    0

ちなみに接続文字列はApp.configから取得しています。

中身はこんな感じです。

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <connectionStrings>
    <add name="connection" connectionString="Data Source=XE;User ID=hoge;Password=fuga;"></add>
  </connectionStrings>
</configuration>

<実行結果1>
f:id:nomurabbit:20131201223320p:plain

上手くデータが取得できました!

<プログラム2>
目標はマスタメンテ用のWebサービスを作ることなので、

次はWebサービスを作ってみることにします。

open System
open System.IO
open System.Data
open System.Configuration
open Oracle.DataAccess.Client
open FSharpWcfServiceApplicationTemplate.Contracts

type Service1() =
    interface IService1 with
        member x.GetOracle value =

            // 接続文字列の取得
            let conStr = ConfigurationManager.ConnectionStrings.Item "string1"
            let con    = new OracleConnection(conStr.ToString())
            
            // SQLの定義
            let sqlStr = "SELECT * FROM MEMBER WHERE ID = " + value
            let cmd    = new OracleCommand(sqlStr, con)
            
            con.Open()
            
            // データの取得
            let reader = cmd.ExecuteReader()
            try
                try
                    let a = reader.Read()
                    sprintf "%s %s %s %s" (reader.GetString(0)) (reader.GetString(1)) (reader.GetString(2)) (reader.GetString(3))
                with
                    | :? FormatException as e ->
                        e.Message
                    | :? IOException as e ->
                        e.ToString()
                    | _  as e->
                        "???"
            finally
                reader.Close()
                con.Close()

<実行結果2>
デバッグで引数に"2"を渡して実行してみた結果がこちら。

f:id:nomurabbit:20131201224856p:plain

こちらも上手く値が返ってきました。

<プログラム3>
それでは最後に、C#で書かれた適当なクライアントから

先ほど作ったWebサービスをサービス参照で呼び出してみます。

public Form1()
{
    InitializeComponent();
}

private void button1_Click(object sender, EventArgs e)
{
    var webService = new FSservice.Service1Client();

    this.textBox1.Text = webService.GetOracle("3");
}

<実行結果3>
f:id:nomurabbit:20131201230943p:plain

おー!値が取得できました!

<まとめ>
F#を使って(というかADO.NETを使って)Oracleにアクセスすることができました。

取得したデータをF#でいかに扱うかを勉強していきたいと思います。

F# AdventCalender 2013 7日目は以上です。

明日は@n_enotさんの「F# で System.Reflection(仮)」です。

Hello Haskell!

<はじめに>
なんてことはない、単にHaskellを書いてみたかったというプログラム。


<プログラム>

main = putStrLn "Hello Haskell!"


<まとめ>
これから勉強していきます。

PhotoCameraを使ってみる

<はじめに>
スマホアプリにカメラは外せないので調べてみました。写真を撮ってカメラロールに保存するだけの簡単なプログラムを書いてみました。


<プログラム>

public partial class MainPage : PhoneApplicationPage
{
    //-----------------------------------
    // インスタンス変数
    //
    int photoCounter = 0;
    PhotoCamera photoCamera;
    MediaLibrary mediaLibrary;

    //-----------------------------------
    // コンストラクタ
    //
    public MainPage()
    {
        InitializeComponent();
        InitializePhotoCamera();
        InitializeMediaLibrary();
    }

    //-----------------------------------
    // photoCamera初期化
    //
    public void InitializePhotoCamera()
    {
        photoCamera = new PhotoCamera(Microsoft.Devices.CameraType.FrontFacing);

        viewfinderBrush.SetSource(photoCamera);

        photoCamera.CaptureImageAvailable += new EventHandler<ContentReadyEventArgs>(photoCamera_CaptureImageAvailable);
    }

    //-----------------------------------
    // mediaLibrary初期化
    //
    private void InitializeMediaLibrary()
    {
        mediaLibrary = new MediaLibrary();
    }

    //-----------------------------------
    // キャンバスをタップ
    //
    private void canvas1_Tap(object sender, GestureEventArgs e)
    {
        try
        {
            photoCamera.CaptureImage();
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }
    }

    //-----------------------------------
    // イメージの取得
    //
    void photoCamera_CaptureImageAvailable(object sender, ContentReadyEventArgs e)
    {
        try
        {
            photoCounter++;

            string fileName = photoCounter + ".jpg";

            mediaLibrary.SavePictureToCameraRoll(fileName, e.ImageStream);

        }
        catch (Exception ex)
        {
            Dispatcher.BeginInvoke(() => MessageBox.Show(ex.Message));
        }
    }
}


<まとめ>
やってることはphotoCameraのインスタンスを生成して、CaptureImageAvailableイベントに画像を保存するメソッドを定義して、photoCameraのCaptureImageメソッドを呼び出しているだけです。ただし、これだけだとカメラで取得した画像の上下がわけわかんなくなってしまうので、WP自体の回転に応じて画面も回転させてやらないといけません。

Compass、Motion、ときどきGyroscope

<はじめに>
WP7で使えるセンサーについて調べてみました。フレームワークで使えそうなクラスにGyroscope、Compass、Motionがあったので、それぞれを使って実装を試してみました。


<プログラム>

public partial class MainPage : PhoneApplicationPage
{
    //--------------------------------------------
    // インスタンス変数
    //
    Gyroscope gyroscope;
    Compass compass;
    Motion motion;

    //--------------------------------------------
    // コンストラクタ
    //
    public MainPage()
    {
        InitializeComponent();

        GyroscopeInitialize();
        CompassInitialize();
        MotionInitialize();
    }

    #region センサー初期化メソッド

    //--------------------------------------------
    // ジャイロスコープ
    //
    public void GyroscopeInitialize()
    {
        gyroscope = new Gyroscope();

        gyroscope.CurrentValueChanged += new EventHandler<SensorReadingEventArgs<GyroscopeReading>>(gyroscope_CurrentValueChanged);

        //gyroscope.Start();
    }

    //--------------------------------------------
    // コンパス
    //
    public void CompassInitialize()
    {
        compass = new Compass();

        compass.CurrentValueChanged += new EventHandler<SensorReadingEventArgs<CompassReading>>(compass_CurrentValueChanged);

        compass.Start();
    }

    //--------------------------------------------
    // モーション
    //
    public void MotionInitialize()
    {
        motion = new Motion();

        motion.CurrentValueChanged += new EventHandler<SensorReadingEventArgs<MotionReading>>(motion_CurrentValueChanged);

        motion.Start();
    }

    #endregion 

    #region イベント用メソッド

    //--------------------------------------------
    // ジャイロスコープ
    //
    void gyroscope_CurrentValueChanged(object sender, SensorReadingEventArgs<GyroscopeReading> e)
    {
        GyroscopeReading gyroscopeReading = e.SensorReading;

        Vector3 rotationRate = gyroscopeReading.RotationRate;

        Dispatcher.BeginInvoke(() => this.textBlockRotationX_value.Text = rotationRate.X.ToString());
        Dispatcher.BeginInvoke(() => this.textBlockRotationY_value.Text = rotationRate.Y.ToString());
        Dispatcher.BeginInvoke(() => this.textBlockRotationZ_value.Text = rotationRate.Z.ToString());
    }

    //--------------------------------------------
    // コンパス
    //
    void compass_CurrentValueChanged(object sender, SensorReadingEventArgs<CompassReading> e)
    {
        CompassReading compassReading = e.SensorReading;

        double headingAccuracy     = compassReading.HeadingAccuracy;
        double magneticHeading     = compassReading.MagneticHeading;
        Vector3 magnetometerRating = compassReading.MagnetometerReading;
        double trueHeading         = compassReading.TrueHeading;

        Dispatcher.BeginInvoke(() => this.textBlockheadingAccuracy_value.Text = headingAccuracy.ToString());
        Dispatcher.BeginInvoke(() => this.textBlockMagnetic_value.Text        = magneticHeading.ToString());

        Dispatcher.BeginInvoke(() => this.textBlockMagnetX_value.Text = magnetometerRating.X.ToString());
        Dispatcher.BeginInvoke(() => this.textBlockMagnetY_value.Text = magnetometerRating.Y.ToString());
        Dispatcher.BeginInvoke(() => this.textBlockMagnetZ_value.Text = magnetometerRating.Z.ToString());

        Dispatcher.BeginInvoke(() => this.textBlockTrueHeading_value.Text     = trueHeading.ToString());
    }

    //--------------------------------------------
    // モーション
    //
    void motion_CurrentValueChanged(object sender, SensorReadingEventArgs<MotionReading> e)
    {
        MotionReading motionReading = e.SensorReading;

        AttitudeReading attitude   = motionReading.Attitude;
        Vector3 deviceAcceleration = motionReading.DeviceAcceleration;
        Vector3 deviceRotatingRate = motionReading.DeviceRotationRate;
        Vector3 Gravity            = motionReading.Gravity;

        Dispatcher.BeginInvoke(() => this.textBlockPitch_value .Text = attitude.Pitch.ToString());
        Dispatcher.BeginInvoke(() => this.textBlockYaw_value.Text    = attitude.Yaw.ToString());
        Dispatcher.BeginInvoke(() => this.textBlockRoll_value.Text   = attitude.Roll.ToString());
    }

    #endregion
}


<まとめ>
端末に機能がないのかGyroscopeは上手く使えなかったのですが、CompassとMotionからは値の取得ができました。センサー関連のクラスは使い方がほぼ同じなのでいろいろ活用できそうです。