Mac Mini(201006) に Ubuntu を入れる

仕事で小型のサーバーが必要になったので色々選定してたら、「この間でたMacMiniLinuxいれたらいいよねー」ってことになった。

勢いで注文して普通にBootCampでやろうとしたけど結構ややこしかった(というか無理矢理っぽい)のでメモ。

1. BootCampでパーティションを作る

この辺はまぁいつもの感じ。

アプリケーション->ユーティリティ->BootCampアシスタント

を起動して、Linux入れるようにパーティションを作る。
一応、OSXは残した状態にするので、OSX=80GB と残りに分割。

その後、Windowsをインストールするか聞いてくるけど無視して終了。

2. rEFItのインストール

この辺もいつもの感じで。

http://refit.sourceforge.net/

上記からrEFItの最新バージョン (〜.dmg) をダウンロードしてインストール。

インストール後、ターミナルで以下実行して有効にする。

$ cd /efi/refit
$ ./enable.sh

3. UbuntuのインストールCDを作成

公式のインストーラを使うと普通に失敗します。
原因は、MacMiniのchipsetドライバ(MCP89)にカーネルが対応しておらず、CDドライブもHDDドライブも認識されないため。

どうやら最新のlinux-kernel2.6.34では対応している様子だが、UbuntuDebianのtestingでも対象のkernelじゃない。
Ubuntu10.04のkernelでもパッチ当てればイケるっぽいので、探してみたら ここhttp://macbookpro7-1.daviey.com/)にパッチ適用ずみのインストーラーイメージを発見。

ということで、上記から 「ubuntu-10.04-desktop-amd64-macbook71.iso」をダンロードしてCDに焼く。

4. CDからブートしてUbuntuのインストール

※ちなみに、最初HDMI->デジタルで画面出力してたけどうまくいかなかったので、ここで Mini DisplayPort->RGB出力に繋ぎ換えた。HDMIでも何とかする方法があるかもしれないけど未確認。

1) CD入れて「C」キー押しっぱなしで電源投入してCDからブートさせる。


2) Ubuntuの起動メニューが表示されたら、一応「vga=791」だけ付け加えてインストーラを起動した。(これは別に無くてもいいかも。)


3) 画面が激しく乱れて、ファミコン状態になっているかも知れないけど、まぁあとでなんとかするとしてそのままインストールを続行する。


4) パーティションは適当に、/boot:512MB(ext3), swap:4096MB, /:残り(xfs) にした。結構時間かかる。


5) 途中ネットワークカードの認識で躓くけど、まぁこれも後でどうにかなるので気にせず続行。


6) GRUBのインストール場所は 4 で作成した /bootパーティションに指定した。rEFItの関係でデフォルトのMBRにしちゃうと何となく駄目な気がしたので。


そんなこんなでインストール完了。再起動。
再起動時に、rEFItの起動メニューにUbuntuが追加されてるので、Ubuntuを選択して起動させる。

5. ドライバとかのインストール

とりあえずUbuntuがあがってきたけど、

  • 画面がひどい(ファミコン状態)
  • ネットワークつながらない
  • 日本語環境が中途半端

という感じなので、なんとかする。

1) NICドライバの入手
MacMiniNICBroadCom 57765 なので、インターネットの使える別マシンBroadComのサイトhttp://ja.broadcom.com/support/ethernet_nic/netxtreme_desktop.php)からLinux用のドライバ(tg3)をダウンロード&解凍してUSBメモリとかでUbuntuにコピーする。


2) NICドライバのインストール
Ubuntu上で以下を実行

$ cd [ドライバの入っているフォルダ]
$ tar xzvf tg3-3.105h.tar.gz
$ cd tg3-3.105h
$ make
$ sudo insmod tg3.ko
$ sudo make install

再起動すればNICが使えるようになっているはず。
このあとは有線LAN繋いで作業。(DHCPじゃ無い場合は ネットワーク設定要)


3) とりあえず最新にアップデート

$ sudo apt-get update
$ sudo apt-get upgrade

わんさかと。


4) ディスプレイドライバと無線LANドライバのインストール
ディスプレイドライバと無線LANドライバは、システム → システム管理 → ハードウェア・ドライバ からインストール可能。それぞれ有効にして再起動すればおk。

これでようやく画面がきれいに表示されるようになった。あとは日本語環境くらい。


5) 言語環境の設定

システム → システム管理 → 言語サポート から、標準語言語を日本語に。
あといらない言語が入ってるので、英語&日本語以外のいらない言語のチェックを外して削除しておく。

あとはいつもの感じで足したり引いたりでお好みの環境を構築。

※ちなみに、rEFItでデフォルトの起動OSを変更したい場合は、OSX側で、/efi/refit/refit.conf の 「legacyfirst」を有効に(コメント外す)すれば良いです。


こんな感じでUbuntuが使えるようになった。結構面倒くさい。
もう少ししたら、色々情報が出てきてもっと簡単で正確になると思うので、急ぎでない場合はもう少し待ったほうがいいかも。

クエリのベンチマーク

仕事でクエリの最適化するのに簡単なベンチマークを採る必要があったので作った。探した方が早いかと思ったけど単純に同じクエリを必要回数発行してトータル時間見るだけなので自分が使いやすければそれでおk。あんまり変わらないと思うけどAPに合わせてPHPで書いてみた。単体で動いてどこでも使えるようにPEAR使ってないのでコマンドライン用に書くのがめんどくさい。

#!/usr/bin/php
<?php

($argc == 1) ?  Bench::usage() : $params = Bench::parse_args($argv);

$bench = new Bench($params);
$bench->bootstrap();



class Bench
{
    var
        $params = array();
    
    function __construct($params)
    {
        $this->params = $params;
    }
    
    function bootstrap()
    {
        $con = @mysql_connect(
                             $this->params['dbhost'],
                             $this->params['dbuser'],
                             $this->params['dbpass']
                             ) || die(sprintf("[ERROR %d]: %s\n", mysql_errno(), mysql_error()));
        @mysql_select_db($this->params['dbname']) || die(sprintf("[ERROR %d]: %s\n", mysql_errno(), mysql_error()));

        $this->bench();
        
        mysql_close();
    }
    
    function output($file, $queries, $begin, $end)
    {
       echo sprintf('[%s]: %d queries %d times total %s sec (avg. %s sec).', $file, count($queries), $this->params['count'], 
                    round($end - $begin, 5), round(($end - $begin)/$this->params['count'], 5)) , "\n"; 
    }
    
    function execute($file)
    {
        $_queries = explode(';', file_get_contents($file));
        foreach($_queries as $query)
        {
            if(trim($query) == '') continue;
            $query = ($this->params['cache'])
                      ? preg_replace('/SELECT[\s\t\n\r]+(SQL_NO_CACHE)?/i', 'SELECT ', $query)
                      : preg_replace('/SELECT[\s\t\n\r]+(SQL_NO_CACHE)?/i', 'SELECT SQL_NO_CACHE ', $query);
            mysql_query($query) || die(sprintf("[ERROR %d]: %s on '%s'\n", mysql_errno(), mysql_error(), $file));
            $queries[] = $query;
        }
        $begin = Bench::get_microtime();
        for($i=0; $i<$this->params['count']; $i++)
        {
            foreach($queries as $query) mysql_query($query);
        }
        $end = Bench::get_microtime();
        $this->output($file, $queries, $begin, $end);
    }

    function bench()
    {
        foreach ($this->params['files'] as $file)
        {
            if (is_dir($file))
            {
                $_files = glob(rtrim($file, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . '*.sql');
                if (!empty($_files))
                {
                    foreach($_files as $_file)
                    {
                        $this->execute($_file);
                    }
                }
            }
            else
            {
                $this->execute($file); 
            }
        }
    }

    function usage()
    {
    ?>
    Usage: bench [options] file ... 

    The options are as follows:
        -h   Database Host     (default: localhost)
        -u   Database User     (default: root)
        -p   Database Password (default: '')
        -d   Database Name     (default: mysql)
        -n   Repeat Count      (default: 1000)
        -c   Using Query Cache (default: false)      

    <?php
        exit();
    }

    function parse_args($args)
    {
        $script = array_shift($args);
        $params = array(
                        'dbhost' => 'localhost',
                        'dbuser' => 'root',
                        'dbpass' => '',
                        'dbname' => 'mysql',
                        'count'  => 1000,
                        'cache'  => false,
                        'files' => array()
                    );
        $options = array(
                        '-h' => 'dbhost',
                        '-u' => 'dbuser',
                        '-p' => 'dbpass',
                        '-d' => 'dbname',
                        '-n' => 'count',
                        '-c' => 'cache',
                    );
        $key = '';
        foreach ($args as $arg)
        {
            if($key)
            {
                switch($key)
                {
                    case 'count':
                        $params[$key] = intval($arg);
                        break;
                    case 'cache':
                        $params[$key] = in_array($arg, array('0','false')) ? false : true;
                        break;
                    default:
                        $params[$key] = $arg;
                }
                $key = '';
            }
            else if(isset($options[$arg]))
            {
                $key = $options[$arg];
            }
            else
            {
                $params['files'][] = $arg;
            }
        }
        if(empty($params['files'])) Bench::usage();
        foreach ($params['files'] as $file)
        {
            if(!is_dir($file) && !is_file($file)) Bench::usage();
        }
        
        return $params;
    }

    function get_microtime()
    {
        list($usec, $sec) = explode(" ", microtime());
        return ((float)$usec + (float)$sec);
    }
}
?>

適当なディレクトリに『bench.php』とか適当な名前で保存して実行権限つけて使います。
スイッチも単純なものしかないけど、

$ ./bench.php

    Usage: bench [options] file ... 

    The options are as follows:
        -h   Database Host     (default: localhost)
        -u   Database User     (default: root)
        -p   Database Password (default: '')
        -d   Database Name     (default: mysql)
        -n   Repeat Count      (default: 1000)
        -c   Using Query Cache (default: false)      

みたいな感じで。あとは測定したいクエリを『test.sql』とかに書いて、

$ cat test.sql
SELECT * FROM users;
SELECT * FROM entris;


$ ./bench.php -d DB名 test.sql
[test.sql]: 2 queries 1000 times total 0.46662 sec (avg. 0.00047 sec).

な感じで使えます。

  • デフォルトはクエリキャッシュを無効にする(SQL_NO_CACHEを自動付加)ようになってるのでキャッシュ有効にする場合は -c true オプションつけて実行してください。(別途my.iniとかでクエリキャッシュを有効にしておく必要有り)
  • 複数ファイルをテストしたいときはそのままファイル名をスペースで繋げて実行してください。
  • ファイル名の代わりにディレクトリ名を指定すればディレクトリ内の *.sql をすべてテストできます。

ITバレーカンファレンス@松山にいってきた

先日11/22に松山でITバレーカンファレンスがあったので行ってきた。

松山でこういった集まりは珍しいし、僕自身も参加するのは初めてだったけど行って良かった。良い刺激になりました。(懇親会に参加できなかったのが非常に悔やまれる。。。)

もう誰か書いてるかもしれないけど自分なりに感想などを書いてみる。

サイボウズはなぜ松山でつくるのか?

自社の開発・開発者にこだわりを持っていることがとてもうらやましい。
請負の仕事に追われがちな地方の中小企業ではなかなか難しそうだけど、自社提案・自社製品の開発における姿勢や手法は見習うところが多いと思う。あとポニョみようと思った。

最初は誰でもDQN

  • ウノウ株式会社 CTO尾藤さん
  • 過去のメーリングリストでの発言紹介「Q. Linuxの使い方が分かりません」「A. つらいでしょうが頑張ってください」
  • インターネット、Linuxとの出会い→JE,konの真鍋さんが同高専卒→俺にもできんじゃね?→Vine Linux for SPARCの開発に参加
  • 勉強会ブーム
    • 地方でももっとやろうよ
    • メリット(外部からの刺激、技術力アップ、人脈の広がり、懇親会楽しい)
    • 一人でやってると技術力はアップしない。技術に慣れるだけ。
  • オープンでいこう→Give & Take
  • 結論:「恐 れ な い」
  • 「Q.地方で勉強会したらきてくれますか?」 → 「A.自費でも参加します。」

まず尾藤さんが着ていた「/dev/null」Tシャツが気になった。あれは欲しい。
内容は面白くて笑いも起こっていたけど、恐れないというのはとても大事だと思う。地方だからといって勉強会できないワケじゃないし業界について行けないワケじゃない。恐れずにやってみることが大事。地方で勉強会したら着てくれるらしいwコレは期待。

産官学で行う未来のICT人材発掘・啓発

  • 愛媛大学 小林教授
  • Teenagerへのエンジニアイメージの払拭と人材発掘への取り組み
  • EPOCH@まつやまの発端の経緯
    • 単なる産官学連携はつまらない
    • インターハイや甲子園のように将来のエンジニアが「松山」を目指すように
  • EPOCH@まつやま
    • 純粋なプログラミング能力を試す大会。
    • ビンゴやオセロなども取り入れゲーム性も高めた。
    • 県内だけでなく県外からも多数の参加あり
    • 去年よりも参加条件が厳しく(2名以下のチーム→2名1組のチーム)なったけど今年は去年以上の参加申し込み

EPOCH@まつやまのとりくみは去年から知ってたけど経緯が分かって面白かった。
今年は見に行けなかったけどせっかく地元で面白いことやってるので来年から注目してみよっと。

成功する技術者

  • サイボウズラボ 代表取締役 畑さん
  • 基本重要。→とにかく何が重要か分からなくてもやっておくべき。
  • アセンブリ言語はコンピュータの仕組みが分かって良い。知ってると知らないとではコードの質がちがう。
  • 技術力+社会人力が必要。→コミュニケーション能力や人から教えてもらえる能力も大事なこと。
  • 信頼は実績に宿る。→良い技術者になるにはコツコツ積み重ねが必要。
  • 35才定年説。→意識の持ちよう。会社組織の中でも開発者としてあり続けることは可能。
  • かっこよさ。→エンジニアの地位向上のためには子供が憧れるようなかっこよさも必要。
  • エンジニアとしての成功の定義は人それぞれ。

自分にとって成功の定義がどこにあるのか考えたことなかったけど、多分自分を含めた誰かが幸せになるようなものを作りたいというのは根底にあると思う。全然具体的なものじゃないけど、この根っこの部分がブレると自分は多分ダメ。このへんでお金のためとか会社のためとか言い出すと不安定になる。あくまでも自分の作るものの先にはユーザがいることは忘れないでおきたい。


発表者の皆さんはいずれも愛媛・松山に関わりのあるひとばかりでとても刺激のある内容でした。企画してくださった関係者の皆さんありがとうございました。
「鉄は熱いうちに打て」じゃないですが、この流れで地元の勉強会ブームなどが沸き起こるとすごいうれしい。というか自分で企画しろていうことですね。わかります。

PLANEXのNAS(MZK-NAS02)をなんとかする

家のNASがぶっ壊れたので、RAID1対応で安いものをAmazonで探して買ってみた。
HDD無しだったけど同じくAmazonで安い500GBのHDDを2本買って合計30000円以内だったのでかなりお得な感じだと思う。

到着してからwktkしながら箱から出してセットアップしていざ使おうとしたけど、何となく気になったのでtelnetしてみたらすんなりログインできた。なんというセキュリティ。

ローカルだし自宅だしまぁいいかと思って見てたら、なんか色々「なってない」感じだったのでなんとかした。

1. sambaの設定ファイル

他のLinuxサーバ同様samba使ってファイル共有を行う仕様だけど、設定ファイル見たらtypoあったりcharset指定なかったりでそりゃないだろっていう状態なので以下のように修正。

・globalセクションにcharset設定を追加

unix charset = UTF-8
dos charset = CP932
display charset = UTF-8

・デフォルトで用意されている homes セクションにtypoがあるので修正

[homes]
× pash = /content/home/%S
↓
○ path = /content/home/%S

2. 起動スクリプト修正

「iTuneサーバ対応」とか「DLNA対応」とか「BitTorrent対応」とか正直使わないので停止しようとしたけど、せっかく用意されているサービス管理コマンド(initdconfig)が使えない状態になっているので起動スクリプトの修正。

・「/etc/init.d/mt-daapd」の先頭に以下を追加

#!/bin/bash
#
# DAAP 
#
# chkconfig: 2345 99 41
# description: DAAP server
# processname: mt-daapd

・「/etc/init.d/digital5」の先頭に以下を追加

#! /bin/sh
#
# digital5 
#
# chkconfig: 2345 98 42
# description: digital5 server
# processname: digital5

・「/etc/init.d/btd2」の先頭部分を以下のように修正

#!/bin/bash
#
# btd   This shell script takes care of starting and stopping
#       standalonv btd
#
# chkconfig: 2345 60 50
# description: btd is a BitTorrent Server daemon, which is the program \
#              that answers incoming BitTorrent service requests.
# processname: btd

3. サービス設定

起動スクリプトを修正したらinitdconfigの管理下に置くために以下コマンドを実施

# initdconfig --add mt-daapd
# initdconfig --add digital5
# initdconfig --add btd

これでサービスの管理をinitdconfigで操作できる。

とりあえずデフォルトで配備されているrc.d配下のシンボリックリンクを削除

# rm -rf /etc/rc.d/rc?.d/[S,K]*mt-daapd
# rm -rf /etc/rc.d/rc?.d/[S,K]*digital5
# rm -rf /etc/rc.d/rc?.d/[S,K]*btd

あとはサービス起動の設定をinitdconfigで実施

# initdconfig --level 2345 mt-daapd off
# initdconfig --level 2345 digital5 off
# initdconfig --level 2345 btd off

4. アラートメールの設定

デフォルトでは「/var/nascfg/scripts/notification.pl」でHDDがFULLの時、CPUのオーバーロード時、Raidの縮退モード時にアラートメールを送ることができるっぽいのだが動かない。というか自動起動しようとしてるけどスクリプトのエラーで動いてない。
さらにメール送信の設定や、サービスの起動などがGUIの管理画面から弄れない。
せっかく用意しているなら使えるようにしとけと思うのだが、なんだろねこれ。

まず、普通に実行するとperlのモジュールがいろいろ見つかりませんエラーがでる。多分スクリプトと同じディレクトリにモジュール色々おいてるけど@INCに追加してないのが原因。perl -I でやっても良いけどとりあえずソースを修正しておく。
あと、cpuの使用率チェックのところで、$cpu->{total} ってなってるけどこれってidle含むから常に100%じゃないの?
チェックするならiowaitとかuserとかになると思うんだがなぁ。。。

ということでパッチ作成。

--- notification.org.pl 2008-10-21 22:55:52.665724000 +0900
+++ notification.pl     2008-10-21 23:10:08.065724000 +0900
@@ -1,4 +1,5 @@
 #!/usr/bin/perl
+use lib '/var/nascfg/scripts';
 use Sys::Statistics::Linux::DiskUsage;
 use Sys::Statistics::Linux;
 use Mail::Sendmail;
@@ -275,12 +276,12 @@
  sleep(1);
  my $stats = $lxs->get;
  my $cpu   = $stats->{CpuStats}->{cpu};
- if($cpu->{total}>= $gCpuPer) 
+ if($cpu->{idle}<= 100-$gCpuPer) 
  {
    
    $time = localtime; 
    $Msg = "**************************************************************\n";   
-   $Msg .= "Cpu usage is $cpu->{total}%  on $gIP.\n";
+   $Msg .= "Cpu idle is $cpu->{idle}%  on $gIP.\n";
    $Msg .= "Please kill unnecessary processes .\n"; 
    $Msg .= "Mail sent at: $time \n ";
    $Msg .= "**************************************************************\n";

とりあえずcpuはidleの比率見て判断するようにした。

あとは、「/var/nascfg/CfgFile.txt」に以下設定を書き込めばよい。

ServerIp:192.168.1.1;         # smtpサーバのIP
EmailId:test@example.com;     # アラートの送信先(To:)
DiskPer:90;                   # HDD使用率警告しきい値(%)
DiskCriticalPer:95;           # HDD使用率臨界値(%)
CpuPer:100;                   # CPU使用率警告しきい値(%)
TimeDelay:10;                 # チェック間隔(分)
FromEmailId:root@example.com; # アラートメールの送信元(From:)

5. よくわからないもの

デフォルトでCPU使用率がやたらと高い。topでみると /etc/MemoryDriver/otabd の占有率が高すぎる。
名前からして、おそらくメモリーカードリーダのドライバ関係じゃないかと。

これも使わないので思い切って無効にしちゃう。

# rm /etc/rc.d/*/S98otab




[2008.10.22 追記]
これ切っちゃうと本体の「RAID」REDが赤色に点灯してしまうみたい。うーん。
一緒にMitacGPIOていうモジュールをロードするようになってて、これが多分前面パネルのRED関係のモジュールなんじゃないかと思われる。

RAID異常のアラートはメールで飛んでくるからまぁいいけど、なんか気持ち悪いのでモジュールのロードだけしておく。

# insmod /etc/MemoryDriver/MitacGPIO.ko

という感じでロードすればREDも正常に戻るみたい。



これであとは再起動して正常動作確認すればおk。
今のところウチはこれで問題なく動いてる。なんとなくパフォーマンスも良くなったような気がしないでもない。

もちろん必要に応じてFTPTELNET(SSHつかえるので)つぶしたりすればさらに良いかもしれない。
RPM使えるのでどうにかすればソフトウエア追加してごにょごにょもできるかもしれないけど、正直この機械でそこまでする気は沸かないなぁという感じ。

多分デフォルトだとパフォーマンス悪くてぶちぶち切れたりして使い物にならないんじゃないかと思うんだけど、あんまり言うとPLANEXに悪いのでこのへんにしておく。

Akelos0.9がきてるっぽいのでメモ(設定ファイル編)

久しぶりにアップデートしたらAkelosが待望?の0.9(REV.1196)になってたのでCHANGELOGの内容をメモ。

今回は設定ファイルをベースに変更内容を追いかけてみる。

YAMLベースの設定ファイルが使えるようになった。

AkelosでもようやくYAML形式の設定ファイルをサポートし始めたみたい。
「*.yml」を「AK_APP_DIR/config」ディレクトリに突っ込めば自動的に読み込んでくれるっぽい。
運用環境用は「production」、開発用は「development」、テスト用は「test」を利用できる。新しい要素で「default」セクションが使えるようになっているので、共通要素は多分ここに記述すればいい。
旧設定ファイルの「config/config.php」は定数の設定等でそのまま利用できるみたいだけど、データベースの設定は後述のdatabase.ymlを作成しないとエラーを吐く。

あと、YAMLのキャッシュファイルは「config/cache」配下に作られるみたい。希望としては「tmp/cache/config」にして欲しいのだけど。。。

セットアップ後デフォルトで整備されるYAMLファイルは以下。

infrector.yml ... 単語の単数形<=>複数形の変換関連

default:
    pluralize:  # 複数形への変換
        rules:  # 一定のルールで変換されるもの。上から順に評価されてマッチした時点で終了。

            /sis$/i: ses # 例えばコレだと「〜sis」で終わる単語は「〜ses」を複数形として扱
う。

        uncountable: # 複数形変換しない単語を列挙
            - equipment
            - information # こんな感じ

        irreguler:  # その他の変換ルール。単純に「単数形: 複数形」の形式で記述

            person: peaple
            man: men
            child: children # こんな感じ

    singlize:   # 単数形への変換
         rules:
         uncountable:
         irregulre:    # 子セクションの記述は複数形のときと同じ

多分あんまり弄ることはない。主にmodel内でのプロパティの命名に使われたり、view内でのループ使用時の自動処理に使われる。複数形<=>単数形の変換が気に入らない場合はこのファイルを弄れば良い。

sessions.yml ... セッション関連

default:
    enabled: true  # セッションを有効にする
    handler:
        type: 1 # セッションハンドラを指定(1=File based,2=AdoDB,3=Memcache)
        options:  # ハンドラ固有のオプションを指定
               lifeTime: 3600  # セッションの保持期間

               # ハンドラが1(File)のときは以下のオプションが利用可能
               save_path: ${AK_TMP_DIR}

               # ハンドラが2(AdoDB)の場合は以下のオプションが利用可能
               memoryCaching: true  # メモリキャッシュの使う場合はtrue(デフォルト)
               automaticSerialization: true # 値のシリアライズを自動で行う場合はtrue(デフォルト)

               # ハンドラが3(Memcache)の場合は以下のオプションが利用可能
               servers:
                   - localhost:11211
                   - 192.168.1.1:11211  # こんな感じでMemcachedサーバを列挙できる

セッションの処理にハンドラを使用できるようになってる。いままでファイルかDBかの2択だったのでこれは結構ありがたい。ハンドラの自作も割と簡単にできるし。

AdoDBを使う場合は「lib/AkCache/AkAdodbCache.php」、Memcacheを使う場合は「lib/AkCache/AkMemcache.php」がそれぞれハンドラとしてインクルードされる。

AdoDBの場合、新しく追加された「cache_data」テーブルにセッションが格納されるので旧バージョンのようにsession用のテーブルを作る必要はない。「cache_data」はセッション以外のキャッシュデータにも利用されるのでこの方が確かに効率がいい。

Memcacheの場合はソケット使ってmemcachedサーバと通信してるっぽいのでPHP拡張機能なくても多分おk。

mailer.yml ... メール送信関連

default:
    server_settings:
      address: smtp.gmail.com  # 送信に使用するSMTPサーバのアドレス
      port: 587                # SMTPサーバのポート番号
      domain: localhost        # 
      user_name: username@gmail.com # SMTP認証に使用するユーザ名
      password: 1234           # 同じくパスワード
      authentication: login    # 認証の種類(plain,login,cram_md5)

    # 他にも多分以下の値を設定可能
    delivery_method: php   # 送信にsendmail使うかsmtp使うか
    perform_deliveries = true;
    deliveries:
        - test@example.com    # 送信時に自動配送されるEmailアドレスを列挙(test用?)
    charset: ISO-2022-JP      # 送信に使用する文字コード
    content_type: text/plain  # Content-Type
    mime_version: 1.0         # mime_version
    implicit_parts_order:     # multipartが指定されたときの順序
        - multipart/alternative
        - text/html
        - text/enriched
        - text/plain

リビジョンみるとちょっと前からAkActionMailerが使えるようになっていたみたい(知らなかった)。

caching.yml ... キャッシュ関連

default:
    enabled: true  # キャッシュ機能を使用するかどうか
    handler:
        type: 1    # ハンドラを指定する(1=PEAR,2=AdoDB,3=Memcache)
        options:
                lifeTime: 3000   # キャッシュの生存期間 
            # ここからはハンドラ固有のオプション 以下は1(PEAR)の場合
                cacheDir: ${AK_TMP_DIR}/cache  # キャッシュファイルの保存先
                hashedDirectoryLevel: 2        # キャッシュファイルを生成するディレクトリ深度
                fileLocking: true   # キャッシュファイルの排他ロックを行う(デフォルト)
                writeControl: true  # 書込時にキャッシュの破壊・改竄チェック(デフォルト)
                readControl: true   # 読込時にキャッシュの破壊・改竄チェック(デフォルト)
                readControlType: crc32 # キャッシュハッシュ生成に使用する関数(crc32,md5,strle)
                pearErrorMode:  ${E_USER_ERROR} # PEARのエラーモード(内部的にPEARのCache::Liteを使用しているため)
                onlyMemoryCaching: true   # メモリキャッシュのみを使用する
                memoryCachingLimit: 10000 # メモリキャッシュの上限
                fileNameProtection: true  # ファイル名の保護を行う(デフォルト) 
                automaticCleaningFactor: false # キャッシュの整理を自動的に行う

            # 2(AdoDB),3(Memcache)は「sessions.yml」の記述と同じ

アプリケーションの高速化に関わる部分なのでキャッシュ機能の充実はうれしい追加項目。
キャッシュはページキャッシュ、アクションキャッシュ等コントローラから透過的に生成されて利用される。こまかい挙動はまだ把握できてないので色々実験する必要がありそう。

database.yml ... DB設定関連。※「DEFAULT-database.yml」を複製して作成する。

production:
        type: mysql
        database_file: 
        host: localhost
        port: 
        database_name: test
        user: root
        password: 
        options: 

# 以下productionセクションと同様に「development」「test」セクションを記述
# ※テーブル名は慣例に従って「〜_dev」「〜_tests」が推奨されている。
# 仮にtestテーブルを運用や開発用と同名にした場合 script/test 実行時にクリアされるので注意。

今までconfig.phpに記述していたときと内容に変化はない。
現段階ではまだencoding指定はできないみたいなので、Mysql等でSET NAMESしたいときなどはソース弄らないとダメね。。

その他の設定ファイル

オリジナルの設定ファイルを作りたい場合は「config」ディレクトリ内に「myconf.yml」みたいに適当な名前で作成すればよい。

あとは適宜メソッド内で以下を呼び出せばおk。

 $Config = new AkConfig();
 $myconf = $Config->get('myconf');
    • -

設定ファイル見た感じでは、Railsの細かい所の移植+運用を意識した機能追加を中心に更新されているような感じがする。

あとは0.8以前との互換性が少し気になるところではあるけど、後日コントローラ周りの変更点を追いかけてその辺を確認してみようと思う。

Akelosで作ったアプリケーションを本番環境に配置する

Akelosでアプリケーションを作って、いざ公開する際に本番環境が以下のいずれかに当てはまる場合は正常に動作しない場合があるので注意が必要。

  • mod_rewriteが使えない。
  • 公開URLが「http://[DOMAIN_NAME]/」じゃない。
  • 「/public」を公開ルートに設定できない。

とりあえず、それぞれきちんと対策を取れば正常に動作するので途中で諦めて泣かないこと。

mod_rewriteが使えない。

ApacherewriteモジュールなどのURLリライティング機能が提供されていない場合や、.htaccessRewriteを有効にできない場合などはview内でのURLの記述に注意する必要がある。

たとえば以下のようなURLをviewに記述してしまうと本番環境では正常に動作しない。

<a href="entry/show/id">hoge</a>

これはrewriteが使用できない場合、フロントコントローラにパラメータが渡されずURLマッピングが行われないため。
面倒でもview内のURLはURLヘルパーを使用して記述するようにすること。

<%= link_to 'hoge', :controller => 'entry', :action => 'show', id => 'id' %>

このように書くことで、あとは「config/config.php」のAK_URL_REWRITE_ENABLEDの値をfalseにするだけですべて正常に機能するようになる。

<?php

defined('AK_URL_REWRITE_ENABLED') ? null : define('AK_URL_REWRITE_ENABLED', true);
  ↓
defined('AK_URL_REWRITE_ENABLED') ? null : define('AK_URL_REWRITE_ENABLED', false);

公開URLが「http://[DOMAIN_NAME]/」じゃない。

標準では公開先URLが「http://[DOMAIN_NAME]/」のときに正常に動作するように.htaccessが記述されている。
公開先が「http://[DOMAIN_NAME]/hoge/」とかの場合は.htaccessのRewriteBaseを適切に記述すればおk。

<IfModule mod_rewrite.c>
  RewriteEngine on

  # ↓この行を追加する
  RewriteBase /hoge

  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteRule ^(.*)$ index.php?ak=$1 [L,QSA]
</IfModule>

また、公開先URLと公開ディレクトリの実体が違う場合はhttpd.conf等でAliasディレクティブの設定を行う必要がある。

 Alias /hoge /home/hoge/public

「/public」を公開ルートに設定できない。

Akelosでは静的ファイルはpublicディレクトリ内に配置するようになっており、このディレクトリを公開ルートに設定して動作させるように設計されている。
Apacheの場合、公開ルートを設定する場合、

  • 専用サーバであればDocumentRootの設定を変更
  • VirtualHostであればセクション内のDocumentRootを変更
  • Alias設定等でpublicディレクトリへの参照設定を行う

などが考えられるが、これらはすべてApacheの設定ファイル(.htaccessは不可)を直接編集(もしくはWEBコントロールパネルなどで設定)する必要がある。しかし、環境によってはこれらの設定変更が許可されていない場合があり困ったことになる。

この場合、若干力業になるがアプリケーションのディレクトリ構成と設定ファイルをいくつか変更することで問題を回避することができる。

デフォルト状態ではAkelosで作ったアプリケーションは以下のような構成になっているはず。

/
├ .htaccess
├ index.php
├ akelos/
├ app/
├ config/
├ public/
├ docs/
├ script/
├ test/
├ tmp/
└ log/

※作り方によってはakelosフォルダは別フォルダに配置している場合もあります。

このうち公開に必要なのは .htaccess,index.php,akelos/,app/,config/,public/,tmp/,log/ になるので公開先の構成は以下のような感じ

/
├ .htaccess
├ index.php
├ akelos/
├ app/
├ config/
├ public/
├ tmp/
└ log/

この状態でpublicディレクトリに公開ルートを設定すれば問題ないのだが、無理な場合はまず、適当な名前でディレクトリを作りpublicディレクトリ以外をすべてそのディレクトリへ放り込む。

/
├ public/
└ framework /
   ├ .htaccess
   ├ index.php
   ├ akelos/
   ├ app/
   ├ config/
   ├ tmp/
   └ log/

このあと、publicディレクトリの中身をすべて一階層上に移動させ、空になったpublicディレクトリは削除する。
すると最終的に構成は以下のような感じになる。

/
├ .htacess
├ index.php
├ robots.txt
├ mod_rewrite_text_file.txt
├ images/
├ javascripts/
├ stylesheets/
└ framework/
   ├ .htaccess
   ├ index.php
   ├ akelos/
   ├ app/
   ├ config/
   ├ tmp/
   └ log/

このままアクセスしても当然エラーがでるのでいくつか設定ファイルの編集を行う。

まず、直下のindex.php(元はpublic/index.php

<?php
if(!defined('AK_CONFIG_INCLUDED')){

                 // ↓この行のconfig.phpへのパスを書き換える
if(!file_exists(dirname(__FILE__).DIRECTORY_SEPARATOR.'..'.DIRECTORY_SEPARATOR.'config'.DIRECTORY_SEPARATOR.'config.php')){
        define('AK_ENVIRONMENT', 'setup');
        error_reporting(E_ALL);
        @ini_set('display_errors', 1);
        require(dirname(__FILE__).DIRECTORY_SEPARATOR.'..'.DIRECTORY_SEPARATOR.
        'app'.DIRECTORY_SEPARATOR.'controllers'.DIRECTORY_SEPARATOR.'framework_setup_controller.php');
        exit;
    }else{
                 // ↓この行のconfig.phpへのパスを書き換える
include_once(dirname(__FILE__).DIRECTORY_SEPARATOR.'..'.DIRECTORY_SEPARATOR.'config'.DIRECTORY_SEPARATOR.'config.php');
    }
}

ファイル内に2カ所config.phpへのパスが記述されているので変更後のファイルパスに変更する。


さらに、framework/config/boot.php(元はconfig/boot.php)を編集。

<?php

defined('DS') ? null : define('DS', DIRECTORY_SEPARATOR);
defined('AK_BASE_DIR') ? null : define('AK_BASE_DIR', str_replace(DS.'config'.DS.'boot.php','',__FILE__));
defined('AK_FRAMEWORK_DIR') ? null : define('AK_FRAMEWORK_DIR', AK_BASE_DIR);
defined('AK_LIB_DIR') ? null : define('AK_LIB_DIR',AK_FRAMEWORK_DIR.DS.'lib');

// ↓ この行を追加する
define('AK_PUBLIC_DIR', realpath(AK_BASE_DIR.DS.'..'));

require_once(AK_LIB_DIR.DS.'constants.php');
?>

boot.phpにAK_PUBLIC_DIRを設定し公開ルートのディレクトリのパスを変更後のパスに設定する。

以上の設定でpublicディレクトリが公開ルートに設定できなくても正常にアプリケーションを動作させることができるようになる。



ということで、まだまだAkelosはユーザ数も他のフレームワークに比べて圧倒的に少ないし、それに比例して情報量も少ないので結構ハマることもあるかもしれないけどソースは読みやすいので頑張ればなんとかなるよ。ということです。

Akelosで作ったアプリケーションを本番環境に配置する

Akelosでアプリケーションを作って、いざ公開する際に本番環境が以下のいずれかに当てはまる場合は正常に動作しない場合があるので注意が必要。

  • mod_rewriteが使えない。
  • 公開URLが「http://[DOMAIN_NAME]/」じゃない。
  • 「/public」を公開ルートに設定できない。

とりあえず、それぞれきちんと対策を取れば正常に動作するので途中で諦めて泣かないこと。

mod_rewriteが使えない。

ApacherewriteモジュールなどのURLリライティング機能が提供されていない場合や、.htaccessRewriteを有効にできない場合などはview内でのURLの記述に注意する必要がある。

たとえば以下のようなURLをviewに記述してしまうと本番環境では正常に動作しない。

<a href="entry/show/id">hoge</a>

これではrewriteが使用できない場合、フロントコントローラにパラメータが渡されずURLマッピングが行われない。
面倒でもview内のURLはURLヘルパーを使用して記述するようにすること。

<%= link_to 'hoge', :controller => 'entry', :action => 'show', id => 'id' %>

このように書くことで、あとは「config/config.php」のAK_URL_REWRITE_ENABLEDの値をfalseにするだけですべて正常に機能するようになる。

<?php

defined('AK_URL_REWRITE_ENABLED') ? null : define('AK_URL_REWRITE_ENABLED', true);
  ↓
defined('AK_URL_REWRITE_ENABLED') ? null : define('AK_URL_REWRITE_ENABLED', false);

公開URLが「http://[DOMAIN_NAME]/」じゃない。

標準では公開先URLが「http://[DOMAIN_NAME]/」のときに正常に動作するように.htaccessが記述されている。
公開先が「http://[DOMAIN_NAME]/hoge/」とかの場合は.htaccessのRewriteBaseを適切に記述すればおk。

<IfModule mod_rewrite.c>
  RewriteEngine on

  # ↓この行を追加する
  RewriteBase /hoge

  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteRule ^(.*)$ index.php?ak=$1 [L,QSA]
</IfModule>

また、公開先URLと公開ディレクトリの実体が違う場合はhttpd.conf等でAliasディレクティブの設定を行う必要がある。

 Alias /hoge /home/hoge/public

「/public」を公開ルートに設定できない。

Akelosでは静的ファイルはpublicディレクトリ内に配置するようになっており、このディレクトリを公開ルートに設定して動作させるように設計されている。
Apacheの場合、公開ルートを設定する場合、

  • 専用サーバであればDocumentRootの設定を変更
  • VirtualHostであればセクション内のDocumentRootを変更
  • Alias設定等でpublicディレクトリへの参照設定を行う

などが考えられるが、これらはすべてApacheの設定ファイル(.htaccessは不可)を直接編集(もしくはWEBコントロールパネルなどで設定)する必要がある。しかし、環境によってはこれらの設定変更が許可されていない場合があり困ったことになる。

この場合、若干力業になるがアプリケーションのディレクトリ構成と設定ファイルをいくつか変更することで問題を回避することができる。

デフォルト状態ではAkelosで作ったアプリケーションは以下のような構成になっているはず。

/
├ .htaccess
├ index.php
├ akelos/
├ app/
├ config/
├ public/
├ docs/
├ script/
├ test/
├ tmp/
└ log/

※作り方によってはakelosフォルダは別フォルダに配置している場合もあります。

このうち公開に必要なのは .htaccess,index.php,akelos/,app/,config/,public/,tmp/,log/ になるので公開先の構成は以下のような感じ

/
├ .htaccess
├ index.php
├ akelos/
├ app/
├ config/
├ public/
├ tmp/
└ log/

この状態でpublicディレクトリに公開ルートを設定すれば問題ないのだが、無理な場合はまず、適当な名前でディレクトリを作りpublicディレクトリ以外をすべてそのディレクトリへ放り込む。

/
├ public/
└ framework /
   ├ .htaccess
   ├ index.php
   ├ akelos/
   ├ app/
   ├ config/
   ├ tmp/
   └ log/

このあと、publicディレクトリの中身をすべて一階層上に移動させ、空になったpublicディレクトリは削除する。
すると最終的に構成は以下のような感じになる。

/
├ .htacess
├ index.php
├ robots.txt
├ mod_rewrite_text_file.txt
├ images/
├ javascripts/
├ stylesheets/
└ framework/
   ├ .htaccess
   ├ index.php
   ├ akelos/
   ├ app/
   ├ config/
   ├ tmp/
   └ log/

このままアクセスしても当然エラーがでるのでいくつか設定ファイルの編集を行う。

まず、直下のindex.php(元はpublic/index.php

<?php
if(!defined('AK_CONFIG_INCLUDED')){

                 // ↓この行のconfig.phpへのパスを書き換える
if(!file_exists(dirname(__FILE__).DIRECTORY_SEPARATOR.'..'.DIRECTORY_SEPARATOR.'config'.DIRECTORY_SEPARATOR.'config.php')){
        define('AK_ENVIRONMENT', 'setup');
        error_reporting(E_ALL);
        @ini_set('display_errors', 1);
        require(dirname(__FILE__).DIRECTORY_SEPARATOR.'..'.DIRECTORY_SEPARATOR.
        'app'.DIRECTORY_SEPARATOR.'controllers'.DIRECTORY_SEPARATOR.'framework_setup_controller.php');
        exit;
    }else{
                 // ↓この行のconfig.phpへのパスを書き換える
include_once(dirname(__FILE__).DIRECTORY_SEPARATOR.'..'.DIRECTORY_SEPARATOR.'config'.DIRECTORY_SEPARATOR.'config.php');
    }
}

ファイル内に2カ所config.phpへのパスが記述されているので変更後のファイルパスに変更する。


さらに、framework/config/boot.php(元はconfig/boot.php)を編集。

<?php

defined('DS') ? null : define('DS', DIRECTORY_SEPARATOR);
defined('AK_BASE_DIR') ? null : define('AK_BASE_DIR', str_replace(DS.'config'.DS.'boot.php','',__FILE__));
defined('AK_FRAMEWORK_DIR') ? null : define('AK_FRAMEWORK_DIR', AK_BASE_DIR);
defined('AK_LIB_DIR') ? null : define('AK_LIB_DIR',AK_FRAMEWORK_DIR.DS.'lib');

// ↓ この行を追加する
define('AK_PUBLIC_DIR', realpath(AK_BASE_DIR.DS.'..'));

require_once(AK_LIB_DIR.DS.'constants.php');
?>

boot.phpにAK_PUBLIC_DIRを設定し公開ルートのディレクトリのパスを変更後のパスに設定する。

以上の設定でpublicディレクトリが公開ルートに設定できなくても正常にアプリケーションを動作させることができるようになる。



ということで、まだまだAkelosはユーザ数も他のフレームワークに比べて圧倒的に少ないし、それに比例して情報量も少ないので結構ハマることもあるかもしれないけどソースは読みやすいので頑張ればなんとかなるよ。ということです。