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; };
パッチを書こう
動いてしかるべき物が別のOSだと動かなかったりしたときにはちゃんと調べてパッチを書こう。
パッチを書こう
パッチを書こうパッチを書こうパッチを書こうパッチを書こう
パッチを書こうパッチを書こうパッチを書こうパッチを書こう
パッチを書こう
Ubuntu 11.04 (Natty) で perl がインストール出来ない場合の理由と対策
追記
perlbrew 最新版では修正済みです。
patchperl にパッチ投げておきました。
perlbrewも最新のpatchperl を使うようになったので、失敗する場合はもう一度perlbrew の最新版を再インストールしてください(perlbrew のバージョン番号は変わってないので注意)
追記終わり
原因 - 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の解説は日本語でも大量にあるのでそれを読むとすぐに使えるようになってしまうのでそのあとの+αを。
モジュール
はじめからperlの環境とcpanmが入ってるのでdot-filesを管理している人はモジュールを一気に入れたほうがモジュール不足でイラッとしなくて済むと思う。(とくにモジュール周りやテスト周り)
必要なものをいちいち選んでインストールするのが面倒なので富豪的に普段使っているものをどんどん入れた。
https://github.com/punytan/dot-files/blob/master/build-env/06_perl-modules.list
この中で入らなかったのは
- Text::MeCab
- MP3::Tag
の二つだけなのでXML関連をはじめ、諸々ライブラリはOSにインストール済みな雰囲気。これは大変便利。
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時間ほど。