perl のリリースサイクルと perlbrew の共存

perl のリリースサイクルが短くなったこの頃、みなさまいかがお過ごしでしょうか。

リリースサイクル短期化による影響

perlbrew を使ってリリース毎にバージョンを切り替えたりしていると、意外と面倒に感じるのがインストール済みのモジュール類を別バージョンに移行することではないでしょうか?
さらに頻繁にリリースされるとなると、移行するのが面倒ですね。

移行時にやるべき事

移行時には、

  • 既存のバージョンにインストールされているモジュール一覧の抽出
  • 新バージョンのインストール
  • 既存のバージョンにインストールされていたモジュールを新バージョンでインストール

結構手間がかかります。

そこで

こんな bash script を ~/.bashrc などに追記しておくと楽に移行できる tips をお届けします。

ちなみに、最新の perlbrew 0.25 からはエラーが起きた際には exit 1; をよんでいるので、シェルの戻り値で処理を継続するかどうかを判定することができるようになりました(パッチ投げたらマージしてもらえた。やったね!)

function migrate {
    if [ $# -ne 1 ]; then
        cat << EOM
Usage:
    migrate [perl-version]
    migrate perl-5.14.1
EOM

    else
        echo "@@@@@ Start migration to $1"; sleep 1;

        echo "@@@@@ Installing ExtUtils::Installed"; sleep 1;
        cpanm ExtUtils::Installed;

        echo "@@@@@ Extracting all modules"; sleep 1;
        rm /tmp/modules.list;
        perl -MExtUtils::Installed -E 'say for ExtUtils::Installed->new->modules' > /tmp/modules.list;

        echo "@@@@@ Upgrading perlbrew"; sleep 1;
        curl -L http://xrl.us/perlbrewinstall | bash;
        source ~/perl5/perlbrew/etc/bashrc;

        echo "@@@@@ Installing $1"; sleep 1;
        perlbrew install "$1" -v &&

        echo "@@@@@ Switching new environment"; sleep 1;
        perlbrew switch "$1" &&

        echo "@@@@@ Installing cpanminus for new environment"; sleep 1;
        perlbrew install-cpanm &&

        echo "@@@@@ Installing all modules into new environment"; sleep 1;
        cpanm < /tmp/modules.list;

        echo "@@@@@ Re-running cpanminus to check everything is OK"; sleep 1;
        cpanm < /tmp/modules.list;

        echo "@@@@@ Done migration!"
        perl -V;
    fi
}

Access-Control-Allow-Origin を追加するmiddlewareを書いてた

一ヶ月くらい前に GitHub - punytan/Plack-Middleware-AccessControlAllowOrigin: Add Access-Control-Allow-Origin header を書きました

使い方

至って簡単ですね。ただ、AccessControlAllowOriginって名前が長すぎる

    builder {
        enable 'Plack::Middleware::AccessControlAllowOrigin', origin => '*';
        $app;
    };

補足

類似モジュールに Plack::Middleware::CrossOrigin なんてのがあるんですがこれはやってることが多すぎる。
Access-Control-Allow-Origin 付けたい時にはこれで需要の99.9%はカバーできるんじゃないかと思うので、こんな物を作ってみた次第。

パッチを書こう

動いてしかるべき物が別のOSだと動かなかったりしたときにはちゃんと調べてパッチを書こう。

パッチを書こう

パッチを書こうパッチを書こうパッチを書こうパッチを書こう

パッチを書こうパッチを書こうパッチを書こうパッチを書こう

パッチを書こう

Ubuntu 11.04 (Natty) で perl がインストール出来ない場合の理由と対策

追記

perlbrew 最新版では修正済みです。
patchperl にパッチ投げておきました。
perlbrewも最新のpatchperl を使うようになったので、失敗する場合はもう一度perlbrew の最新版を再インストールしてください(perlbrew のバージョン番号は変わってないので注意)
追記終わり

http://d.hatena.ne.jp/Itisango/20110504/1304487042 の原因。

原因 - Ubuntu の math ライブラリ諸々がディレクトリごと移動した

Configure はデフォルトで

/usr/local/lib
/lib
/usr/lib
/usr/lib64

を読みに行くところ、Ubuntu Natty からは libm などのライブラリが

/lib/i386-linux-gnu
/usr/lib/i386-linux-gnu

などに移動しているためリンクできずにリンカがエラーを吐く。

対策

Configure の plibpth にこれらのディレクトリを加えてやれば解決できる。

ライブラリのパスは環境に依存してるので

$ gcc -print-search-dirs | grep libraries | cut -f2 - -d= | tr ':' '\n'

などして確認できる。

おまけ

make test の時に

../lib/User/pwent.t ............................................... ok
../lib/feature/unicode_strings.t .................................. ok
x2p/s2p.t ......................................................... ok

Test Summary Report
-------------------
op/stash.t                                                      (Wstat: 0 Tests: 31 Failed: 0)
  TODO passed:   26
../cpan/Memoize/t/errors.t                                      (Wstat: 11 Tests: 6 Failed: 0)
  Non-zero wait status: 11
  Parse errors: Bad plan.  You planned 11 tests but ran 6.
../ext/ODBM_File/t/odbm.t                                       (Wstat: 32512 Tests: 0 Failed: 0)
  Non-zero exit status: 127
  Parse errors: No plan found in TAP output
../lib/DBM_Filter/t/01error.t                                   (Wstat: 32512 Tests: 3 Failed: 0)
  Non-zero exit status: 127
  Parse errors: Bad plan.  You planned 21 tests but ran 3.
Files=1808, Tests=349977, 930 wallclock secs (73.67 usr 14.43 sys + 511.11 cusr 72.13 csys = 671.34 CPU)
Result: FAIL
make: *** [test_harness] Error 3

のようなエラーが出た場合は libgdbm のリンクに失敗しているため、

$ perlbrew install perl-5.12.3 # もしここで失敗したら
$ cd ~/perl5/perlbrew/build/perl-5.12.3/
$ locate libgdbm | grep o$
/usr/lib/i386-linux-gnu/libgdbm.so
/usr/lib/i386-linux-gnu/libgdbm_compat.so
$ vim ext/ODBM_File/hints/linux.pl

として ext/ODBM_File/hints/linux.pl の条件式をlocate で確認したパスに合わせて次のように書き換える

if (-e '/usr/lib/libgdbm_compat.so' or -e '/usr/lib64/libgdbm_compat.so'
    or -e '/usr/lib/i386-linux-gnu/libgdbm.so' or -e '/usr/lib/i386-linux-gnu/libgdbm_compat.so'
) {

パーミッションが -r--r--r-- なので強制的に上書き。その後、

$ make clean && make && make test
$ make install

すればあら不思議インストールされています。

$ perlbrew list
* perl-5.12.1
  perl-5.12.3
  /usr/bin/perl (5.10.1)

ということでライブラリのパスが変わってしまったために起きた問題でした。

dotcloud雑感

みんながhello worldばかりやっているのでちょっとしたアプリつくってみようということで作ったもの。 Docker Cloud - Build, Ship and Run any App, Anywhere

Plack::Middleware::* なnamespaceを列挙して、モジュール名クリックでPODを読み込んでくれる超便利な仕上がりとなっております。

適当な頻度で更新されるはず。(うまく動いていれば)

ソースはここにおいてあります GitHub - punytan/middleware.punytan.dotcloud.com: Source code of http://middleware.punytan.dotcloud.com/


dotcloudは簡単すぎでhello worldの解説は日本語でも大量にあるのでそれを読むとすぐに使えるようになってしまうのでそのあとの+αを。

ssh

ssh 使うときは info でポートがわかるけれども、

dotcloud ssh foo.bar

みたいにも入れるのでこっちのほうが楽ですね。

モジュール

はじめからperlの環境とcpanmが入ってるのでdot-filesを管理している人はモジュールを一気に入れたほうがモジュール不足でイラッとしなくて済むと思う。(とくにモジュール周りやテスト周り)

必要なものをいちいち選んでインストールするのが面倒なので富豪的に普段使っているものをどんどん入れた。

https://github.com/punytan/dot-files/blob/master/build-env/06_perl-modules.list
この中で入らなかったのは

の二つだけなのでXML関連をはじめ、諸々ライブラリはOSにインストール済みな雰囲気。これは大変便利。

extlib

これは多分個人の趣味よるかもしれないけれども、CPANに上げてないモジュールはextlib使わずにインストールしてみた。手元の環境と全く同じという訳でもなさそうなのでPP以外に依存してる場合は、同梱するとあとでやや面倒になりそうな気がする。

gitが入ってるぽいので富豪的にモジュールを入れたあとは github などから git clone して make dist 後(あるいは$HOME/shipit-distから持ってきて)、cpanmに渡すだけで楽々インストールできます。

VPSと比べて

VPSだとXMLライブラリのインストールやsshの設定やら諸々手間なことが待っているわけですが、ここまでデプロイするのが楽だと丸投げしたくなってしまいますね!
個人的にはmemcachedが使えるといいなぁという所。

Tatsumaki + AnyEvent::Twitter::Stream を一枚のスクリプトで完結させる方法

これができると嬉しいこと

サーバとクライアントがひとつのプロセスにまとまってクローラー的なプロセスが必要なくなり、監視せずに済むので地味に嬉しい

概要

言われてみれば何だ、という程度ではあるけれども、app.psgiで Twiggy::Server を使い、コネクションを AE::timer で監視し、AE::cv->recv; するという方法をつかえば Tatsumaki::MessageQueue も使えて万々歳。これがなかなか思いつかなかった…

思いつかなかった言い訳

Twitter の userstream は時々切れるので再接続の処理をする必要があった。今までずっとクローラーで while ループ回したりしてたけれども、 while を使って接続が切れるごとに ->recv してるとサーバと一緒に動かすことができなくて悶々とした日々を過ごすこと数ヶ月。

サーバでは builder {} を return していたので、当然 while なんて挟めなかった。

ソース

必要な部分だけ切り取り

use strict;

package PollHandler;
use parent 'Tatsumaki::Handler';
__PACKAGE__->asynchronous(1);
use Tatsumaki::MessageQueue;

sub get {
    my $self = shift;

    my $mq = Tatsumaki::MessageQueue->instance('tweet');
    my $client_id = $self->request->param('client_id')
        or Tatsumaki::Error::HTTP->throw(500, 'client_id is required');
    $mq->poll_once($client_id, sub { $self->on_new_event(@_) });
}

sub on_new_event {
    my $self = shift;
    $self->write(\@_);
    $self->finish;
}

package main;
use AE;
use Plack::Builder;
use Tatsumaki::Application;
use Twiggy::Server;
use AnyEvent::Twitter::Stream;

my $app = Tatsumaki::Application->new([ '/poll' => 'PollHandler' ]);

my $mapp = builder {
    # enable etc...
    $app;
};

my $server = Twiggy::Server->new(
    host => 'example.com',
    port => 5000,
)->register_service($mapp);

my $STREAM_CONN; # we need $STREAM_CONN to keep the availability of stream connection
my $LISTENER;    # we have to declare $LISTENER here, because variables in the timer callback scope are not visible from here

my $w; $w = AE::timer 1, 10, sub {
    return if $STREAM_CONN;

    my $oauth = { ... };

    say "ALERT: wake up";
    $LISTENER = AnyEvent::Twitter::Stream->new(
        %$oauth,
        method     => 'userstream',
        on_error   => sub { $STREAM_CONN = 0; },
        on_eof     => sub { $STREAM_CONN = 0; },
        on_connect => sub { $STREAM_CONN = 1; },
        on_tweet   => sub {
            my $tweet = shift;

            my $mq = Tatsumaki::MessageQueue->instance('tweet');
            $mq->publish({ type => 'tweet', tweet => $tweet });
            $STREAM_CONN = 1;
        }
    );
};

AE::cv->recv;

補足

AnyEvent::HTTP の変更によって AE::T::Stream 0.20 は動かないが、 AE::T::Stream の DEVELOPER RELEASE (0.20_1) だと chunked encoding 周りが fix されているので上げるべし

コンフィ作ってみた

http://mt.endeworks.jp/d-6/2011/04/post-173.htmlデイリーポータルZ:そうだ、肉を脂で煮ればいいんだ を見ていたら食べたくなったので作ってみた。

コンフィとは食材を油に浸してつくるフランスの保存食らしい。今回はオリーブオイルと鳥のモモ肉を使った。

皮はパリパリ、肉はジューシーに仕上がり、フォークだけで肉を簡単に崩せるほどやわらかくできる。
待ち時間さえあれば意外と簡単にできて美味しい。火を通した時間は弱火で2時間ほど。

今回使ったのは国産若鶏モモ肉661グラム581円。

二切れ入っていたので片方はあとで食べる。塩を振って下味をつける

国の定める基準をはるかに上回る高濃度食塩水に漬ける

半日漬けるのはちょっと面倒だったので濃度でカバー。直ちに健康に影響はない。

耐熱容器がなかったので大きめのフライパン+小さめの土鍋で湯煎する

油を温める温度がおおよそ100度らしいので湯煎でも大丈夫っぽい。

使ったオリーブオイル

温める準備をしてる間に高濃度食塩水によって味付けされた肉


オリーブオイルと肉を土鍋に入れる


温める!

あまりぐつぐつ煮るようなことはせず、プクプクと沸騰するくらいがちょうどよさそう。煮えたぎるとオリーブオイルに水が入ってしまう。

効率を高めるためにフタをする


20分ほどすると少し火が通る


だんだん火が通ってくる


裏返して反対の面にも火を通す


一時間ほど経つととりあえず火は通るようだ

しかしこの状態では肉の固さが菜箸を通して伝わってくる。

温め始めて1時間30分。箸がすっと通るようになってくる


あと30分ほど待つ

2時間経過すると肉が柔らかくなっていることが菜箸でつかむだけでもよくわかるようになる。
そうなったらフライパンで油をひかずに皮をパリっと焼き、塩コショウで味付け。

完成

うまい!

味付けは塩コショウのみでも十分美味しい。鶏のパサパサ感は全くなく、大変美味しい肉に仕上がる。

この調理法はかなりいい。