あけましておめでとうございます。
    Fusic 平田です。
    新年気分とは何の関係もない、RAIDのお話です。

    年末にXenサーバのディスクがお亡くなりになったので、ディスク換装してCentOS6.2でKVMサーバを再構築。
    で、ディスク4本なのでどうしようかなーと思いつつRAID5を組んではみたのですが、iowaitが収まらない。
    特に書き込みのほうが苦戦しているようで、仮想サーバがちょっと頑張るたびにロードアベレージが10越えたり。
    これじゃ使い物にならんなあ最悪RAID10で組み直したほうがいいかなあ。。。とか悩んでいる時に以下の記事を発見。
    https://peterkieser.com/2009/11/29/raid-mdraid-stripe_cache_size-vs-write-transfer/
    ※ 記事中のスクリプトまでは試していません。
    書き込みで苦しんでいるならstripe_cache_size増やすと捗るよ!ってことでやってみました。

    サーバスペック:
    Xeon X3230 (4コア) メモリ8GB HDD1TB*4(RAID5, software raid)

    対象のRAIDアレイ(今回はmd3)に対して

    # echo 8192 > /sys/block/md3/md/stripe_cache_size

    と実行して値を書き換えます。
    resyncがかかってしばらくしたら完了したので、あとはtopでだらだら流して様子見。
    仮想サーバ側で何度か負荷の高い処理をしてみてもロードアベレージがさほど上がらなくなったので、とりあえずはよし。

    あとはOS再起動しても動くように、ruleを追加。

    # cat <<EOS > /etc/udev/rules.d/80-md-stripe-cache.rules
    SUBSYSTEM=="block", KERNEL=="md*", ACTION=="change", TEST=="md/stripe_cache_size", ATTR{md/stripe_cache_size}="8192"
    EOS

    今のところ、これで快適に動作しています。
    問題が起きないか、最大限の関心を持って注視を続けることが当面の隠れ業務です。

    ・・・ていうか、そもそもRAID5使わないとかsoftware raid使わないとか別の方策あった気もします。

    追記:
    8192でも微妙につっかえる場面が見受けられたので、結局32768(最大)まで増やしています。
    ページサイズ(=4KB)×stripe_cache_size×ディスク数分のメモリ使うので、あんまし増やしすぎるのも嫌だなーと思ったんですが。
    メモリで困る前にCPU数で困りそうな気がしたのと、メモリは最悪増設できるしなーってことで、とりあえずはこのままで。

      Fusic 北岸です。

      もう今年も終わりますね。
      休みの日に近所でバドミントンをしているのですが、
      昨日で今年最後の分が終わってしまいました。
      打ち損じでカツーンなんて音をさせてばかりではありますが、来年も楽しく頑張ります!

      さてさて、今回のテーマは 「CUIでファイルサイズの合計を調べる」 です。
      すごく基本的な内容ではありますが、以前ちょっと気になって調べたのでまとめておきます。

      ファイルサイズを調べるコマンド

      皆さんは、ファイルサイズを調べる時に、どのようなコマンドを使用されていますか?
      私がすぐに思いつくのは、次のコマンドです。

       $ ls -l

      そして、ディレクトリの容量を調べるなら、このコマンドですね。

       $ du

      しかし、この du というコマンド、きちんとファイルサイズを測れません。

      この du は、ブロックサイズを単位としてサイズを計測しています。

      今回用意したシステムは ブロックサイズが4096バイト(=4.0KB) なので、
      例えば次のような結果が得られます。

      sky@ub1110x64:~/contrail$ ls -l ./substance/
      合計 12
      -rw-rw-r-- 1 sky sky 4097 2011-12-26 07:22 ice_grain
      -rw-rw-r-- 1 sky sky 4096 2011-12-26 07:22 moisture
      sky@ub1110x64:~/contrail$ du -ah ./substance/
      4.0K	./substance/moisture
      8.0K	./substance/ice_grain
      16K	./substance/

      たった1バイトしか違わないのに、du コマンドだと 4.0KB も違う事になっていますね。

      どうやってファイルサイズを測るか

      では、どうすればブロックサイズに左右されずに、
      フォルダ内の容量を測れるのでしょうか。

      調べて分かったのは、 find コマンドです。
      一例を示します。

       $ find ./ -printf "%s\n"

      階層的にディレクトリ内ファイルを検索してくれるコマンド find には、
      そのファイルに関する情報を出力してくれるアクションがあります。

      それが 「-printf」 です。

      「 find ./ 」のみだと、カレントディレクトリ配下のディレクトリの内容を出力するだけですが、
      「-printf」を利用する事により、出力内容を変える事が出来ます。

      ここで使用しているフォーマットは次の通りです。
      %s : ファイルサイズのバイト表示
      \n : 改行

      実行結果の一例を示します。

      sky@ub1110x64:~/contrail$ ls -l *
      sky:
      合計 24
      -rw-rw-r-- 1 sky sky 6789 2011-12-26 07:22 high
      -rw-rw-r-- 1 sky sky 1234 2011-12-26 07:22 light
      -rw-rw-r-- 1 sky sky 9999 2011-12-26 07:22 scraper
       
      substance:
      合計 12
      -rw-rw-r-- 1 sky sky 4097 2011-12-26 07:22 ice_grain
      -rw-rw-r-- 1 sky sky 4096 2011-12-26 07:22 moisture
      sky@ub1110x64:~/contrail$ find ./ -printf "%s : %f\n"
      4096 : ./
      4096 : sky
      1234 : light
      6789 : high
      9999 : scraper
      4096 : substance
      4096 : moisture
      4097 : ice_grain

      ※見やすいようにファイル名(%f)も表示しています。

      sky@ub1110x64:~/contrail$ du -ah
      4.0K	./sky/light
      8.0K	./sky/high
      12K	./sky/scraper
      28K	./sky
      4.0K	./substance/moisture
      8.0K	./substance/ice_grain
      16K	./substance
      48K	.

      ちなみに、次のようにディレクトリ指定を省略すれば、
      カレントディレクトリ配下を検索するため、同じ出力が得られます。

       $ find -printf "%s : %f\n"

      現状のままでは、各ファイルやディレクトリのサイズが列挙されただけで、合計の値が得られていません。
      もう一手間加えます。

      というわけで、 awk コマンドを組み合わせたものがこちらです。

      sky@ub1110x64:~/contrail$ find ./ -printf "%s\n" | awk '{ sum += $1; }; END { print sum }'
      38503

      各ファイルサイズについて、{ sum += $1; }; の部分で次々と足し合わされ、
      END { print sum } の部分によって、最後に1回だけ、変数 sum が出力されます。

      いかがでしょうか。
      私にとって、awk コマンドはまだまだ慣れないものではありますが、
      とても応用が効きそうなコマンドだなと思いました。

      物理をやってたあの頃

      研究室を思い出すと、、、やっぱりまだありました、変なもの、不思議なもの。
      前回は片栗粉でしたが、今回は ペットボトル です。

      それは エッキー って呼ばれてました。
      中身は、500ml いっぱいの水と、砂が4分の1程度、ピンが3、4個ほどだったと思います。

      では、何のためのものなのかと言うと 「液状化現象」 を見るためです。
      液状化っていうと、地震の時に水がしみ出してくるアノ現象ですね。

      使い方としては、
      このエッキーをよく振って、静かに置きます。
      この時、ピンは砂に埋もれて見えない状態になっているはずです。

      この状態で、デコピンなどしてエッキーに刺激を与えると、ピンが飛び出してきます。
      これが、地震後の液状化に対応しています。

      ちなみに最近知ったのですが、
      エッキーって、商品名でした。
      どうも、キットとして売られているようです。

      おしまいです。
      ではでは。

        そろそろ誕生日の萩原です。誕生日プレゼントください。去年も似たようなことを言ったような気がするのは気のせいです。

        最近、CakePHP2を色々触ってまして、色々困ったことがあったので、まとめておこうかなと思います。(CakePHP2.0.4現在)
        (下でCakePHP2.xなんか知りませんと言われてますが・・・)

        AppControllerをapp/Controller以外に置く場合の注意

        CakePHP2からは皆さんご存知の通り、AppController及び、AppModelが、app直下に設置が出来なくなりました。

        CakePHP2ではAppControllerはapp/Controller以下に設置をすること、と言うことになっています。

        しかし、個人的には出来れば、直接アクセスするコントローラとはAppControllerは分けたいところです。

        そこで、AppControllerをapp/Libに設置をしようと考えまして設置を行っていました。

        app/Lib以下にAppControllerを設置後は、AppControllerを継承するコントローラにはApp::usesの記述が必要になります。

        <?php
         
        App::uses('AppController', 'Lib');
         
        class PostsController extends AppController {
         
        }

        しかし、作業をしていく内に、たまにAppController内のアクションが読めないというエラーが出ることがありました。(debug2でも)

        元凶はapp/tmp/cache/persistent/cake_core_file_mapのキャッシュ(こいつがなかなかの曲者です・・・)だと言うことはすぐにわかったのですが、どうにも再現性も取れず、対策がなかなかつかめない状態でした。(1ヶ月くらい悩んでいました・・・)

        結局のところ現象としては

        (1)404ページ(missing controllerなど)にアクセス
        (2)CakeErrorControllerを見に行く
        (3)CakeErrorControllerがapp/Controller以下にセットしていない場合は、CakeコアのCakeErrorControllerを見に行く
        (4)当然、コアのコントローラにApp::usesの記述があるはずもなく、継承するAppControllerの場所としてApp/Controller以下を見に行く
        (5)ないので、CakeコアのAppControllerにアクセスしに行く
        (6)さらに、キャッシュにAppControllerの位置はCakeコアにある、と記述
        (7)その後、通常のシステムのページにアクセスしても、AppControllerとして、CakeコアのAppControllerを見に行く
        (8)App/Lib以下に設置したAppConttroller内のアクションが呼ばれない

        ということが起こっていました。

        解決策としては

        ①AppControllerを素直にApp/Controller内に設置する
        ②CakeErrorControllerをApp/Controller内にコピーしてApp::usesをセットする

        ①はまずまず問題ないく動作をするはずです。

        ②についてはCakeコアでAppControllerを継承しているものが、他には通常あまり使わないであろう、PagesControllerくらいだったので、こちらでもおそらく問題なく動作すると思います。

        (2011/12/15追記)

        LibにAppControllerを置くと言う件について、Libの中にControllerのディレクトリを作ってその中に置けばいいという指摘を頂きました。
        試してみると、app/Lib/Controller/AppController.phpという形で設置をしたら、確かに問題なくusesなしでもapp/Lib/Controller/AppController.phpを見に行ってくれました。
        これならCakeErrorを書き換える必要もなくなるので、これが一番良い解決法かもしれません。

        app以下のクラス名とPlugin以下のクラス名が同名だと誤動作する

        これは具体例を挙げた方が早いと思います。

        app/Controller/PostsController.php(①)と、app/Plugin/Post/Controller/PostsController.php(②)の二つの同名のコントローラがあるとします。

        初めに①にアクセスした後、②にアクセスをしようとすると、①にアクセスをしてしまうというものです。(逆もしかり)

        これが起きてしまう原因はapp/tmp/cache/persistent/cake_core_file_mapのキャッシュがプラグインを考慮していないためです。(またお前か・・・)

        実のところ、AdminPluginを作成してそこに管理画面を実装しようとしていたところでしたので、これはかなり致命的でした。

        解消方法自体はコアを触れば出来なくもないのですが、コアのアップデートなど一切できなくなるのでお勧めはしません。

        どうしても動作させたいのであれば、lib/Cake/Core/App.phpをプラグインを考慮するように直接編集すると、動作はします。

        まぁ、ただ当分はapp以下とPlugin以下で同名のクラスが入るような実装は避けた方が良いでしょう。

        (2011/12/16追記)

        CakePHPチームにチケットを投げてみましたが、同名のクラスは現在使えない、Cake3で計画中と言われました。

        PaginatorのorderにSQLが記述できない

        CakePHP2からPaginatorがコンポーネントに分離されたことは皆さんご存知かとは思いますが、CakePHP2では現在のところPaginatorでorderにSQLがそのまま記述が出来ません。

        例えば

        $this->Paginator->settings = 
            array('order' => array('`hoge` is null ASC')):

        のようなソートを行いたい時に上記のorderが無視されます。(実際に必要な場面がありました・・・)

        これは、コアのPaginatorComponentを見ればわかるのですが、352行目~の記述で

        if ($object->hasField($field)) {
        	$order[$alias . '.' . $field] = $value;
        } elseif ($object->hasField($key, true)) {
        	$order[$field] = $value;
        } elseif (isset($object->{$alias}) && $object->{$alias}->hasField($field, true)) {
        	$order[$alias . '.' . $field] = $value;
        }

        とありまして、例外が全く、無視される形になっています。

        この記述自体は1.3にもあるのですが、1.3では最後にarray_mergeをしているので、SQLも取り込んでくれていたのですが、2.0では無視された状態です。

        どうしても特殊なorderをかけたい場合は現状では素書きのSQLやDBのviewなどで対応しておいた方が良いかもしれません。

        (今回私の場合は、元々orderをかけたかったテーブルがviewだったのでviewにソート用のカラムを泣く泣く追加しました・・・)

        (2011/12/16追記)

        CakePHPチームにチケットを投げてみたところ、orderを文字列で指定したら動くじゃん!って言われたので現在配列で指定したんだけど・・・と返しているところです。

        SSLページでのCookieのセキュア属性を外す方法

        SSLページがあるページとないページが混同する場合、Cookieのセキュア属性が付いていると、セッションを共有できないため、セキュア属性を外してあげる必要があります。

        1.3の場合は以下の対応が必要になります。

        app/config/core.php

        //	Configure::write('Session.save', 'php');
        	Configure::write('Session.save', 'session_custom');

        app/config/session_custom.php

        <?php
         
        if (empty($_SESSION)) {
            ini_set('session.use_trans_sid', 0);
            ini_set('session.name', Configure::read('Session.cookie'));
            ini_set('session.cookie_lifetime', $this->cookieLifeTime);
            ini_set('session.cookie_path', $this->path);
        }
        ini_set('session.cookie_secure', 0);

        これは、コアのcake_session.phpの設定を強引に上書きをしています。

        CakePHP2ではcore.phpに以下の記述をすれば、対応できます。

        Configure::write('Session', array(
            'defaults' => 'php',
            'ini' => array(
                'session.cookie_secure' => 0
            )
        ));

        特に新しいファイルを作成する必要はなく、手軽です。

        CakePHP2.0ではセッションを共有するしないにかかわらず、SSLがあるページとないページが混同するサイトでは、セキュア属性は外した方が良い。

        これは、まずSSLのあるページ(①)でログインをした後、SSLのないページ(②)にアクセスし、その後、①のページにアクセスをすると、ログアウトしてしまうと言う現象のためです。(これは1.3では発生しません)

        詳しい原因についてはまだ追い切れていないのですが、①にアクセスした後、②にアクセスすると①と異なるセッションキーが振られます。(これは当然の話)

        その後①のページにアクセスすると、②で発行されたセッションキーに上書きされてしまうため、ログアウトをしてしまいます。

        以上の理由から、今のところ、SSLがあるページとないページが混同するサイトでは、セキュア属性は外して置いた方が良いと思います。

        (2011/12/16追記)

        CakePHPチームにチケットを投げてみたところ、上記の書き方でセキュア外せばいいじゃん!って言われました。

        最後に

        まだCakePHP2は駆け出しで、問題が色々と出てますが、触っている感じとしては1.3とそう大差なく使えています。そして早いです。

        きっとこれからどんどん良くなっていくと思うので皆さんどんどんさわりましょう!

        後、本当にfile_mapのキャッシュには要注意です!
        ああ・・・app.phpの750行目を消してfile_mapのキャッシュをなかったことにしたい・・・w

          Fusicの中野です。

          表題のとおり、CakePHPのログに関する小ネタを紹介します。
          ちなみに、使っているCakePHPのバージョンは1.3です。(CakePHP2.xなんて知りません)

          CakePHPでConfigure::read(“debug”) > 1の場合は画面にSQLのログが表示されます。
          ですが、運用中ではPHPのエラー表示などがされないように、Configure::read(“debug”) == 0の状態ではないかと思います。
          そうなると、すこしだけSQLの確認をしたいときなどちょっと面倒ですよね。

          CakePHPはConfigure::read(“debug”) > 1の場合、SQLのログはDboSourceの_queriesLogというメンバの配列に格納されていて、どうやらその配列の中身を画面に出力しているようです。

          そこで、こいつの中身が取れれば解決できるので・・・

          $db =& ConnectionManager::getDataSource($Model->useDbConfig);
          $db->fullDebug = true; // ここがfalseだとログを保存しない。$db->fullDebug = Configure::read() > 1みたいになってます。
          $db->_queriesLogMax = 200; // SQLがこの件数こえると配列に保存しないよ的なもの。

          みたいなことをfindを実行する前に書いてあげれば、_queriesLogに登録されるようです。

          だけど、これだと少々めんどいのでBehaviorにまとめてみましょう。

           
          class QueryLogBehavior extends ModelBehavior {
            var $__settings = array();
            var $_queriesLogMax = 999;
           
            function setup( &$Model, $settings = array() ){
             $this->__settings[ $Model->alias ] = array();
           }
           
            function make_query_key( $Model, $query ){ return get_class( $Model ) . "__" .  md5( serialize( $query ) ); }
            function add_query( $key ){
              return "'" . $key . "' = '" . $key . "'";
            }
           
            function beforeFind( &$Model, $query ){
              if( array_key_exists( "log", $query ) and $query["log"] ){
                $db =& ConnectionManager::getDataSource($Model->useDbConfig);
                $db->fullDebug = true;
                $db->_queriesLogMax = $this->_queriesLogMax;
                $key = $this->make_query_key( $Model, $query ); // いらないかも。
                if( array_key_exists( "conditions", $query ) ){
                  $query["conditions"][] = $this->add_query( $key );
                }
                else {
                  $query["conditions"] = array( $this->add_query( $key ) ); 
                }
                $this->__settings[$Model->alias][] = array( $key, $query["log"] );
              }
              return $query;
            }
           
            function afterFind( &$Model, $results, $primary ){
              $db =& ConnectionManager::getDataSource($Model->useDbConfig);
              $db->fullDebug = Configure::read() > 1;
              $db->_queriesLogMax = 200;
           
              $hit_sql = null; $level = LOG_DEBUG;
              foreach( $this->__settings[$Model->alias] as $keypair ){
                list( $key, $level ) = $keypair;
                foreach( $db->_queriesLog as $index => $query_log ){
                  if( preg_match( "/^(.*)" . $this->add_query( $key ) . "(.*)$/", $query_log["query"], $regexp )) {
                    $hit_sql = $regexp[1] . "" . $regexp[2];
                    break;
                  }
                }
              }
              if( !is_null( $hit_sql ) ) $this->log( $hit_sql, $level );
              return true;
            }
          }

          なんかこんな風に適当にBehaviorを追加して

          $this->Hoge->find( "all", array( "contain" => array(), "conditions" => <なんかの条件>, "log" => LOG_INFO ) );

          みたいにしてあげたら、app/tmp/log/debug.logにSQLが記述されます。これで任意のfindの処理のSQLをログにだしたりできます。
          データベースの設定でSQLのログだしとけよとかいうツッコミはなしで。

          { 2011.11.22 }

          autofs + sshfs の設定

            初めまして。
            物理系出身で、新人の北岸です。

            ブログ初投稿ですが、よろしくお願いします。

            今回のテーマは 「autofs を使って、sshfs を利用する」 です。

            単純にsshfsを使うより、
            autofsと組み合わせた方が何かと便利かなーって思ったので、
            このテーマで進めたいと思います。

            というのも、毎回 sshfs コマンドを叩くのも煩わしいですし、
            起動時にマウントさせる設定などしてると、
            ネットに繋がっていない環境ではそこでエラーになってしまいます。

            でも、autofs なら大丈夫!
            そんな感じです。

            用意した環境

            Virtualbox 上にLinux を2台
            1. Ubuntu 11.10 64bit Desktop
            2. CentOS 5.7 64bit

            概要

            Ubuntu にて、
            ・公開鍵認証の設定
            ・autofs の設定
            ・sshfs でマウント
            という流れで進めます。

            公開鍵認証の設定

            root ユーザになり、
            秘密鍵と公開鍵のセットを作成するために次のコマンドを実行します。

            root@ub1110x64:~# ssh-keygen

            この時、秘密鍵の場所は、「/root/.ssh/id_rsa.bright」を指定し、パスフレーズは空で設定しました。

            SSH接続の際に、この秘密鍵を読み込むための設定をします。
            ファイル ~/.ssh/config に、次の設定を記述します。

            Host bright
            User root
            HostName 192.168.55.101
            IdentityFile ~/.ssh/id_rsa.bright

            後は、この公開鍵を CentOS に設置するだけです。
            次の手順で設置しました。

            root@ub1110x64:~# scp .ssh/id_rsa.bright.pub root@192.168.55.101:/root/
            root@ub1110x64:~# ssh root@192.168.55.101
            [root@localhost ~]# mkdir .ssh
            [root@localhost ~]# touch ~/.ssh/authorized_keys
            [root@localhost ~]# cat id_rsa.bright.pub >> .ssh/authorized_keys

            これで無事、次のコマンドなどを実行して、
            Ubuntu からパスワード無しでSSH接続が出来るようになりました。

            root@ub1110x64:~# ssh bright

            autofs の設定

            まず次のコマンドで、sshfs と autofs をインストールします。

            root@ub1110x64:~# apt-get install sshfs autofs

            次に、autofs の設定をしていきます。
            これは2つのファイルに、1行ずつ書くだけです。

            まず、ファイル /etc/auto.master の最終行に、次の一行を追加します。
            /home/sky/bright /etc/auto.sshfs --timeout 0 --ghost

            この設定の意味は、
            ディレクトリ /home/sky/bright に、
            ファイル /etc/auto.sshfs の内容に従ってマウントするというものです。

            --timeout 0

            これは、自動切断をする時間のための設定で、
            ゼロを指定しているため、自動でアンマウントしない設定です。

            --ghost

            これは、実際にアクセスするまでマウントしないという設定です。

            最後に、ファイル /etc/auto.sshfs というファイルを作成して、
            blue -fstype=fuse,allow_other :sshfs\#bright\:/
            だけ記述します。

            この設定の意味は、
            ファイル /etc/auto.master に記述されたディレクトリ上の、
            ディレクトリ blue に sshfs でマウントするというものです。

            -fstype=fuse,allow_other

            これは、sshfs の FUSE options で allow_other を指定するという設定です。
            これを加える事で、例えば一般ユーザ sky でも
            マウントしたディレクトリにアクセス出来るようになります。

            autofs の設定はここまでです。

            最後に、次のコマンドで、autofs を再起動するだけです。

            root@ub1110x64:~# service autofs restart

            autofs の設定に関する余談

            1. もし、/root/.ssh/config ファイルの設定をしていなかったら
            設定ファイル /etc/auto.sshfs に関しては、次のように書かないとマウント出来ません。

            blue -fstype=fuse,allow_other,IdentityFile=/root/.ssh/id_rsa.bright :sshfs\#root@192.168.55.101\:/

            2. 1 の条件で、sshfs コマンドでマウントするとしたら
            次の2つのコマンドを実行する必要があります

            root@ub1110x64:~# mkdir -p /home/sky/bright/blue/
            root@ub1110x64:~# sshfs -o allow_other,IdentityFile=~/.ssh/id_rsa.bright /home/sky/bright/blue/ root@192.168.55.101:/

            マウントの確認

            マウントしたポイントは、/home/sky/bright/blue/ です。

            次のコマンドを実行してみると、
            無事にマウントが出来ている事が確認出来ました。

            root@ub1110x64:~# ll /home/sky/bright/blue/
            合計 112
            drwxr-xr-x 1 root root  4096 2011-11-13 03:58 ./
            drwxr-xr-x 3 root root     0 2011-11-13 13:20 ../
            -rw-r--r-- 1 root root     0 2011-11-13 03:57 .autofsck
            -rw-r--r-- 1 root root     0 2011-10-05 14:17 .autorelabel
            drwxr-xr-x 1 root root  4096 2011-10-28 01:00 bin/
             
            *** (略) ***

            試しに、適当なファイルを作成してみたいと思います。
            今回は Ubuntu の一般ユーザ(sky)でやってみます。

            sky@ub1110x64:~$ cat /etc/issue >> ~/bright/blue/sky.txt
            sky@ub1110x64:~$ ll ~/bright/blue/sky.txt
            -rw-r--r-- 1 root root 20 2011-11-13 04:21 /home/sky/bright/blue/sky.txt

            無事に作成できました。

            CentOS にログインしてみても、確かにファイルは存在してました。

            [root@localhost ~]# ll /sky.txt
            -rw-r--r-- 1 root root 20 11月 13 04:21 /sky.txt
            [root@localhost ~]# cat /sky.txt
            Ubuntu 11.10 \n \l

            おわり

            初投稿で、文章を書くのも苦手で、なかなか苦戦しました。
            準備でもケアレスミスの連続で大変でした。。。
            まだまだ未熟ですが、めげずに頑張っていきます!

            ちなみに、自分の開発環境を Windows から Ubuntu に変更したので、
            積極的にこの設定を使っていこうと思います。

            物理をやってたあの頃

            豆知識ってわけではありませんが、
            物理をやってたあの頃の割とどうでもいい事をつらつらと。。。

            研究室に、片栗粉がありました。
            しかも、料理のためではありません。
            水と混ぜる、それだけのためです。
            それ以外の使い方を見た事がありません!

            なぜ混ぜるのか、
            それは、ダイラタント流体を作るためです。

            もしかすると、テレビなどで、
            白い液体の上を走る人を見たことがあるかと思います。
            アレです。

            このダイラタント流体は、
            圧力を加えると固体のように振る舞い、
            そうでないと液体のような振る舞いをするというものです。

            実際に、水と片栗粉をスプーンでかき混ぜて、
            そのスプーンでその白い液体を叩くと、
            固体のような手応えを受けます。
            一方で、ゆっくりスプーンをあてると、
            液体のように飲み込まれていきます。

            何とも不思議なやつなんです~

            今度こそお終いです。
            ではでは。

              どうやら最終区担当の小山です。

              FusicのPHPMatsuri2011 レポートも最後です。何やらハードルが上がっているように見えますが、そこはスルー力を発揮します。

              PHPMatsuriリレーブログで「FusicがPHPMatsuriに参加すべき意義」というエントリーを書きましたが、「実際はどうだったのか?」について考えてみたいと思います。

              PHPMatsuri前

              前のエントリーはどちらかというと自分個人の考えが強かったのですが、あるとき弊社社長からこんなメールが社内に送信されました。

              “今、気付いたけど、小山君がいいこと書いてました。

              blog.fusic.co.jp/archives/1869

              PHP Matsuri に参加する方々、ぜひ何かを感じて
              帰って来て下さい。”

              会社としても4人を送り込むわけですから、期待しないわけにはいかないです。
              ただ、この時点では4人ともそこまで意気込んではいなかったのではないでしょうか。

              はたしてPHPMatsuriで何を感じたのか

              「PHPMatsuriで何かを感じることができたのか」

              それは今までの3回のエントリーを見ていただければ一目瞭然でしょう。

              傍から見ていても違いが分かるほどです。

              例えば、先日CakePHP2.0のリリースがありましたが(おめでたい!)、
              今まで以上に社内で話題になっているように感じました。
              CakePHP界隈の人の話題もでるようになりました。

              では、「具体的に何が変わったのか」、自分なりに分析してみたいと思います。

              会社の外をより意識するようになった

              PHPMatsuriをはじめとして勉強会やカンファレンスで、最も良い効果のひとつがこれだと思います。
              さらにPHPMatsuriはハカソンイベントです。

              会社の外の人と同じ環境で開発できる

              これができるイベントはなかなかありません。
              ネットを通じて一つのプログラムを開発するのもかなりエキサイティングな体験ですが、
              実際に同じ場所で、いつもと違った人と一緒に開発するのはさらに刺激的です。

              ちなみにこの体験はかなり中毒性があるらしく、PHPMatsuriにリピータが多いことからもそれが証明されているのではないでしょうか。

              ライブラリを「使う」意識から「作る」意識により傾いた

              何かのシステムを作るとき、目指す目標は「システムを完成させること」です。
              ただ、その目の前の目標だけを追っていたら毎回同じように苦労するでしょう。

              「システムを完成させること」と同時に
              「次のシステムでも使えるような機能に」「いつか別のシステムでも使えるような機能に」
              「どこかの誰かが使えるような機能に」
              という意識を持つことで、次のシステムを作るとき楽になるかもしれませんし、
              そういう意識を持つことが結果的にソースコードが綺麗になることにつながります。

              なかなか日々の業務に追われていたら変えたい意識もなかなか変わることはできませんが、
              PHPMatsuriではフレームワークの開発者やライブラリの開発者が一堂に会しています。
              その人たちの考えに少しでも触れることができます。
              むしろ触れずにはいられない環境です。

              さらに「次の日のLT大会」のための、業務でない「何かを」作ります。
              多分PHPMatsuriに行く前の、開発ネタを考えるときから何かを得られたのではないでしょうか。

              プログラムの世界を楽しめた

              何で括ればいいか良い言葉を思いつきませんでしたが、
              PHPMatsuriはPHPやJavaScriptをはじめとした「プログラムを通じて楽しむ環境」だったように思います。
              プログラムの世界を楽しむことができれば、
              35年定年説なんて関係ないでしょうし、日々の仕事も楽しくなることうけあいです。

              PHPMatsuriに行くことを決めた時点でいつも楽しめているんでしょうが、
              PHPMatsuriに参加したことで、いろんな人と交流ができて、さらに楽しむ術を覚えたように思います。
              この楽しみがもっと増えればいいなと思っています。

              結論

              当初のもくろみ以上にPHPMatsuriはFusicのプラスになった

              4人がそれぞれ精一杯過ごせたと思います。
              フレームワークのコアデベロッパに相談したり(貴重!)、
              ハッカー精神よろしくアグレッシブすぎるものを開発したり、
              会社の外の人とはじめて一緒に開発する環境を体験したり、
              さらには全員が最後に成果を発表できて、
              確実にプラスになっています。

              PHPMatsuri青年団の皆様、この場を借りて御礼をいいたいと思います。

              本当にありがとうございました!

              来年

              来年のことを言うと鬼が笑うので、あまり考えないようにしていますが、
              来年もPHPMatsuriが開催されて欲しいと思っています。
              ただ、PHPMatsuriを開催するのに多大な労力がかかっていることも知っています。

              もし来年PHPMatsuriが開催されるなら、
              そのための協力はできる限りしていきたいなと思っています。

              ちなみに

              自分は今年はこんなものを作成していました。
              ハッカー賞次点をいただきました!ありがとうございます!

              何が一番面倒かって仕様が複雑すぎで実装に先が見えないことです。

                3区担当の杉本です。
                PHP Matsuri
                でのハッカソンは10/16に終わりましたが、弊社ではまだマラソンが続いています。

                「ブログを書くまでが”Matsuri”」

                ※リレーブログ形式になったのは初日の誰かさんのせいですね。

                PHP Matsuriについて

                今回、初めてPHP Matsuriに参加しました。また、ハッカソンというのも初めての経験でした。
                コアデベロッパーの方やお世話になっているライブラリの開発者の方にお会いできるのを楽しみにしていました。

                Matsuriでは過ごし方を手探りしながら、初日は講演とワークショップに参加して、日付が変わったところから開発を始めました。
                ただ、もう少しいろんな方とお話しすればよかったなと今は思っています。

                デモ大会での発表について

                ハッカソンでは「CakePHPのbakeで確認画面(添付画像付き)含めたソースを楽して一括生成する」というテーマで参加しました。

                弊社ではCMSや業務系システムなどの案件が多く、「確認画面(添付画像付き)」という要件も少なくありません。
                これが結構面倒な処理になるのですが、「TransitionComponent(hiromi2424さん)」と「FilebinderPlugin」を使うことでかなり簡単に実装ができるようになりました。ほんと感謝感謝ですm(_ _)m
                それぞれのライブラリの使い方については割愛させていただきますが、色々な方が詳しく解説されていますので是非調べてみてください。
                ※弊社ブログでも過去にTransitionComponentについての記事が書かれています。

                ただ、それでも案件毎に、モデル毎に同じ処理を書くのが面倒になってきました。

                「もっと楽に、簡単に、ミスがないように」

                実装するために、確認画面ありのCRUDをbakeを使ってソースを生成したいと思うようになりました。

                そこで、CakePHP1.3+から導入されたTemplatesを使って、コアのbakeをいじらず、実装することにしました。
                今回は即実践投入を考えて、まずはCakePHP1.3で開発。

                CakePHP Templatesについて

                Templatesはcakeディレクトリにあるtemplates/default一式をappにコピーして作っていきます。
                Controller/Modelについてはソースを見れば、修正は簡単でしたが、
                課題はCRUDの4ファイル以外のctpファイルをどう生成するか、でした。

                Matsuriに参加するまではコアのbake周りをいじらないといけないかと思っていましたが、cakephperさんに相談したところ、コアデベロッパーのグラハムさんに直接質問できる機会ができ、templatesを使って任意のctpファイルを生成するサンプルコードを教えてもらい、見事解決しました。

                ちょっと緊張しましたが、グラハムさんとお話ができたこの瞬間が一番楽しかったです。(でもやっぱり英語勉強しないといけませんね。。。)
                本当にMatsuriに参加してよかったです。

                CrudPlusPluginについて

                ブログを書きながら(思いつきで)名前を決めました。
                使い方はapp/pluginsディレクトリに置いてbakeするだけ。

                php cake/console/cake.php bake all

                該当するモデルを選ぶところはいつもと同じです。異なるのは最後にテンプレートを指定するところです。

                ---------------------------------------------------------------
                You have more than one set of templates installed.
                Please choose the template set you wish to use:
                ---------------------------------------------------------------
                1. confirm_with_file
                2. default
                Which bake theme would you like to use? (1/2)
                [1] > 1

                これでadd.ctp/edit.ctp/index.ctp/view.ctpに加えて、add_confirm.ctpも同時に生成されます。今回のハッカソンでは時間が足りず、edit_confirm.ctpまで作れませんでした。
                あと改善したいのはTransitionComponent/FilebinderPluginの存在チェックをして、なければ取得・設置できるような処理を入れたいと考えています。
                近いうちに仕上げて、GitHubで公開します。

                最後に

                今回、目標の一つにCakePHP2.0を学ぶというのを掲げていました。年内にはstableが出るだろうから年明けにはガンガン使い出すという雰囲気でしたので。
                ところが福岡に帰ってきてみると、いつの間にかリリースされているというお土産つき!
                CakePHPワークショップ中にバグを直すという(予期しない)”イベント”があったので、まるで自分が開発チームのような、一緒に2.0をリリースしたような気分に勝手になっていました。
                これはただの妄想ですが、いつも使っているフレームワークやライブラリを開発している方と直に話をすることで、さらにこのフレームワークやライブラリが好きになりました。
                これは今回得たものの中でも予想外のことでした。

                今回このような素晴らしい機会に恵まれたことに感謝しています。
                そして、PHP Matsuriのスタッフの方にはこの場を借りてお礼を言いたいと思います。本当にありがとうございました。

                さて明日は最終走者、弊社小山です。
                初日の安藤さんや吉岡さんのように、熱く”Matsuri”を語って、このリレーマラソンを締め括ってくれると思います。
                みなさん、期待しておいてください。

                それではまたどこかで。

                  おひさしぶりです。
                  今はWindowsPhoneがほしいFusic)櫻川です。

                  さて、今回はPHP開発合宿イベントPHPMatsuriに参加してきました。

                  まずはじめに

                  他の方もブログに書かれていますがPHPMatsuriを表すなら
                  ↓このかっこいい忍者と

                  koyhogeさんの写真を使わせていただいてます。

                  ↓この音楽です。
                  Epic sax guy 10 hours
                  忍者がバックミュージックとしてこの曲をかけ続ける中でみんな徹夜でコーディングをするカオスな空間でしたw

                  ハッカソンの成果

                  今回ハッカソンでやらせていただいたのは「CakePHP2.0Androidアプリ」という内容でやらせていただきました。

                  CakePHP2.0bakeするとAndroidアプリ用のCRUDソースを出力する謎なPluginを作りましたw
                  ※社内ではキモイといわれています。。。

                  使い方

                  1.どちらかでbakeをします。

                  php cake.php Android.bake

                  ↑実行することでネイティブなAndroid用のソース(Java)を出力します。

                  php cake.php Titanium.bake

                  ↑実行することでTitaniumのAndroid用ソース(Javascript)を出力します。

                  2.ビルドします。

                  Javaの場合はeclipseで、Titaniumの場合はTitanium Studioでビルドします。

                  3.実行します。
                  AndroidアプリのCRUD完成!

                  結果

                  結果「全ての作品の中で最も支持された作品を選出し表彰する。ハッカー賞(大賞)を頂きました!!!
                  しかもiPad2まで頂いてしまいました!!!
                  今自分は人生の中で一番輝いています。゚(゚≧□≦゚)゚。
                  自分に投票して頂いた皆様本当にありがとうございます!!

                  ソースコードなのですが現在リファクタリング中ですので完了次第githubで公開させていただきます。

                  最後に

                  このような楽しい祭りを開いて頂いた運営のみなさま本当にありがとうございました。
                  そしてお疲れ様でした!

                  来年も絶対参加します!

                  それでは明日の3番手杉本にバトンタッチです。

                    ブログはお久しぶりです。萩原です。

                    今回は、PHPmatsuriに弊社、小山、櫻川、杉本と、私の4人で行ってきました。

                    PHPmatsuriの感想

                    私は、ハッカソンという形式のイベントは初めてで、LTも初めてでしたので非常に緊張しましたが、何とか無事に発表まで終える事が出来て良かったです。

                    発表でおーと声が上がった時は非常にうれしかったです。
                    後、下記にも載せているホークスのスタメンを出したときに、「何でそんなマニアックな」と言って下さった方、ありがとうございます。
                    あれが一番うれしかったりします(笑)。

                    普段、私はCakePHPを扱っていますが、SymfonyやLithiumなどの他のフレームワークについてはまったくといっていいほど知りませんでしたので、その二つのセッションを両フレームワークの開発者から聞けたことも非常に貴重な機会でした。

                    また、開発風景やLTの発表を見まして、皆さんすごい、もっと自分も頑張らないとと改めて感じました。

                    CsvCombinePlugin

                    さて、今回私がPHPmatsuriで紹介しました、CsvCombinePluginについてご紹介したいと思います。

                    このプラグインはCSVの入出力の処理を簡単に行うことが出来るプラグインです。
                    CakePHP1.3と2.0の両方のブランチをGithubで用意しています。

                    せっかくですのでCakePHP2の方式で紹介したいと思います。

                    まずはこちらのGithubの”cake2″というブランチよりダウンロードしてきて、Pluginディレクトリ内に”CsvCombine”とrenameして下さい。

                    CSVの入力

                    まずはCSVを添付して配列で返すメソッドを紹介します。

                    モデルにBehaviorを宣言します。

                    <?php
                    App::uses('AppModel','Model');
                    CakePlugin::load('CsvCombine');
                    class CsvTest extends AppModel{
                        var $actsAs = array('CsvCombine.CsvImport');
                    }

                    後は、コントローラで列ごとの配列のキー値を指定したらアクションをたたいて完了です。

                    <?php
                    App::uses('AppController','Controller');
                        class CsvTestsController extends AppController{
                        var $name = 'CsvTests';
                     
                        function index(){
                            if ($this->request->is('post')) {
                               /***基本必要な個所***/
                               //配列のキー値を左から指定
                                $list = array('打順', '守備','名前','打率','HR','打点');
                                //このアクションで配列が返ってくる
                                $data = $this->CsvTest->csvData($list);
                                 /***!基本必要な個所***/
                                if ($data === false) {
                                    print_r('MISS');
                                    exit;
                                }
                                print_r($data);
                                exit;
                            }
                     
                        }

                    これで下記の様なCSVを添付すると・・・(PHPmatsuri1日目夜の日のホークスのスタメンです・・・)

                    1,遊,川﨑,.271,1,37
                    2,二,本多,303,0,43
                    3,左,内川,.341,12,73
                    4,三,松田,.283,25,83
                    5,中,長谷川,.293,4,34
                    6,右,福田,.256,1,20
                    7,DH,柴原,.077,0,0
                    8,一,明石,.277,1,12
                    9,捕,山崎,.191,0,11
                    P,投,杉内,.200,0,3
                    

                    以下のような配列が返ってきます。(preで整形しています。

                    Array
                    (
                        [0] => Array
                            (
                                [打順] => 1
                                [守備] => 遊
                                [名前] => 川﨑
                                [打率] => .271
                                [HR] => 1
                                [打点] => 37
                            )
                    
                        [1] => Array
                            (
                                [打順] => 2
                                [守備] => 二
                                [名前] => 本多
                                [打率] => 303
                                [HR] => 0
                                [打点] => 43
                            )
                    
                        [2] => Array
                            (
                                [打順] => 3
                                [守備] => 左
                                [名前] => 内川
                                [打率] => .341
                                [HR] => 12
                                [打点] => 73
                            )
                    
                        [3] => Array
                            (
                                [打順] => 4
                                [守備] => 三
                                [名前] => 松田
                                [打率] => .283
                                [HR] => 25
                                [打点] => 83
                            )
                    
                        [4] => Array
                            (
                                [打順] => 5
                                [守備] => 中
                                [名前] => 長谷川
                                [打率] => .293
                                [HR] => 4
                                [打点] => 34
                            )
                    
                        [5] => Array
                            (
                                [打順] => 6
                                [守備] => 右
                                [名前] => 福田
                                [打率] => .256
                                [HR] => 1
                                [打点] => 20
                            )
                    
                        [6] => Array
                            (
                                [打順] => 7
                                [守備] => DH
                                [名前] => 柴原
                                [打率] => .077
                                [HR] => 0
                                [打点] => 0
                            )
                    
                        [7] => Array
                            (
                                [打順] => 8
                                [守備] => 一
                                [名前] => 明石
                                [打率] => .277
                                [HR] => 1
                                [打点] => 12
                            )
                    
                        [8] => Array
                            (
                                [打順] => 9
                                [守備] => 捕
                                [名前] => 山崎
                                [打率] => .191
                                [HR] => 0
                                [打点] => 11
                            )
                    
                        [9] => Array
                            (
                                [打順] => P
                                [守備] => 投
                                [名前] => 杉内
                                [打率] => .200
                                [HR] => 0
                                [打点] => 3
                            )
                    
                    )
                    

                    CSVの出力

                    CSVの出力はコントローラでComponentを宣言して、出力したい配列を準備してアクションをたたいて完了です。(今度は同日の阪神のスタメンです・・・大阪でしたし。)

                    <?php
                    App::uses('AppController', 'Controller');
                    CakePlugin::load('CsvCombine');
                     
                    /**
                     * ParentEnquetes Controller
                     *
                     * @property ParentEnquete $ParentEnquete
                     */
                    class CsvTestsController extends AppController {
                     
                        var $components = array('CsvCombine.CsvExport');
                     
                        function export(){
                            $list[] = array('1','二','平野','.297','1','28');
                            $list[] = array('2','中','柴田','.280','0','8');
                            $list[] = array('3','遊','鳥谷','.300','5','49');
                            $list[] = array('4','三','新井','.274','17','89');
                            $list[] = array('5','一','ブラゼル','.282','15','66');
                            $list[] = array('6','右','マートン','.316','13','57');
                            $list[] = array('7','左','金本','.218','12','37');
                            $list[] = array('8','捕','藤井','.218','2','15');
                            $list[] = array('9','投','スタンリッジ','.095','0','0');
                     
                            $this->CsvExport->export($list);
                        }
                    }

                    以下のCSVが出力されます。

                    1,二,平野,.297,1,28
                    2,中,柴田,.280,0,8
                    3,遊,鳥谷,.300,5,49
                    4,三,新井,.274,17,89
                    5,一,ブラゼル,.282,15,66
                    6,右,マートン,.316,13,57
                    7,左,金本,.218,12,37
                    8,捕,藤井,.218,2,15
                    9,投,スタンリッジ,.095,0,0
                    

                    以上が、PHPmatsuriで発表してきました、CsvCombinePluginの紹介でした。
                    このプラグインは実際にはオプションで区切り文字など指定が出来ますので、TSVなどにも対応が可能です。
                    GithubのREADMEに詳しく書いているのでそちらもご覧頂けたらと思います。
                    よろしければお使いください!

                    最後に

                    このような、有意義で楽しいイベントを準備、運営していただいた皆さん。ありがとうございました。
                    次も参加したいと思えるイベントでした!

                    それでは、弊社二人目が明日、また書きますのでよろしくお願いします!

                      最近10月14日が楽しみな小山です。

                      @kunitさんのエントリー「受け身ではなく手を動かすイベントの楽しさ」からバトンを受けて、エントリーを書きたいと思います。

                      PHPMatsuri2011が開催されます

                      今年も10月14日15日にPHPMatsuriが開催されます。

                      Fusicも去年に引き続きスポンサーとして参加させていただきます。
                      また、今年は社内より私を含めて合計で、なんと4人が参加します。

                      なぜFusicはPHPMatsuriに参加するのか

                      Fusicは総勢20人弱の会社です。さらにその中で開発者はさらに少ないです。さらにPHPでの開発をメインとするメンバーはさらに少なくなります。FusicのPHP開発者の半分以上が10月14日には大阪にいると思います。

                      去年のPHPMatsuri2010への参加は2人でした。
                      それがなぜ今年4人に増えたのか。それは、それだけPHPMatsuriが有意義なものだと感じたからだと思っています。

                      たった2日を通して得られる大きなもの

                      私は主にCakePHPを使用して開発をしていますが、今の開発手法が正しいのか、もっと良いプラクティスがあるのではないか、他のフレームワークも本当の意味で使ってみたい、その思いは常に感じています。
                      「もっと楽して開発したい」という怠惰の精神です。

                      ただ、普段他の開発者の開発の様子を見ることができるのは社内の人ののみです。
                      社外の勉強会にも参加しますが、その場では技術の発表までで、開発の様子をみることはできません。

                      「他の人の開発の様子を直に見たい。開発の考え方を直に聞きたい。」それを実現できるのがPHPMatsuriの2日間です。

                      「CakePHP2.0はどんな感じなのか?」
                      実際にCakePHP2.0で開発している人、ドキュメント翻訳を手がけている人だけでなく、実際にCakePHP2.0『を』開発しているコアメンバーの人がいます。

                      「他のフレームワークは使いやすいのだろうか?」あれだけ開発者が一同に会するのです。おそらく、あらゆるフレームワークを使っている人が1人、いや3人くらいはいるでしょう。

                      「自分の開発スピードはどんなものだろうか?」実際の他の人のノートPCを覗き込めます(これ、結構おすすめです)。また15日の成果発表LTを見ればその成果をみることができます。

                      私は、去年のPHPMatsuriでは他の開発者に圧倒されました。そしてものすごく刺激になりました。それは今年1年の日々の業務の成果や意識においてプラスになったと思っています。

                      FusicがPHPMatsuriに期待すること

                      Fusicの経営理念に
                      「人が成長できる環境を創造します」
                      「新しい価値を創造します」
                      「人・社会・文化とのつながりを大切にします」

                      の3箇条があります。
                      PHPMatsuriはこの3箇条にマッチすると思いませんか?

                      Fusicは社員の環境と成長を大切にします。それが最終的に会社の利益につながることを知っているからです。

                      今年のPHPMatsuriを終えた後に、参加メンバーにプラスに、そしてFusicにプラスになることを期待しています。

                      明日の@kaz_29さんにバトンを渡します!