D-7 <altijd in beweging>

Day to day life of a Perl/Go/C/C++/whatever hacker. May include anything from tech, food, and family.

2010年02月

モヤモヤさまぁ〜ず2のDVD 7, 8, 9を予約購入。大江アナが相変わらず美しいので、見ながらそう呟いていると横の相方からつめた〜〜〜〜〜い一言が飛んでくるのだが、こればっかりは辞めるつもりはないのであった。我慢せよ。

ところで今回のDVDの予約購入特典として「雨の幡ヶ谷」エピソードとかが*抽選で*あたるらしいんだけど・・・なんで?なんでいれてくれないの?!意味がわかりません!

テレビシリーズもののDVDでこうしてエピソードが削られたりするのが本当に嫌なんですけど、なんとかならないですかね。諸事情で出せないエピソードがたまにあるのはまぁしょうがないけど、しれーっと削られてるのはわざわざ金を出して買ってる身としてはかなり遺憾ですね。ちなみに特にひどいと感じたのは「内村プロデュース」編集しすぎじゃ!。あと、「くりぃむナントカ]」シリーズも妙に混ぜないで全部出して下さいよ・・・。

こんどゴールデンに行くみたいだけど、今まで通りのテイストでちゃんとやってくれるのかなぁ。フォーマット変えられたら、すぐ見るの辞めるとおもうので、そこのところ是非がんばってください>伊藤P

ちなみに特典のテレ東モヤモヤは結構楽しめました。
    このエントリーをはてなブックマークに追加 mixiチェック

本日携帯を忘れていますので、携帯へ連絡しても見られません :(

連絡はtwitterかdaisuke@弊社まで。
    このエントリーをはてなブックマークに追加 mixiチェック

某出版社さんに打ち合わせに行ってきたのだけど、このように自分が普段触れない業界の方と話してると必ず思い出す話がある。それはdaibaさんに紹介してもらったこれ→「ムダと一緒に捨てたもの」。

問屋というシステムと現代のムダを削る話なのだが、まぁ現在の状況がいいとか悪いとかは自分で調べてもないのでとりあえずざっと斜め読みしてもらって、キモは2ページ目の「問屋の裏機能」あたりから「そのせいで技術も低下する」のあたり。

出版社の方と話している限り僕は「(物を作るという意味での)作家」側にいるわけだが、話している際に市場のニーズの事や、現実的な流通の経路やビジネスモデルなんかの話をしてもらってそれに合わせて内容を調節していくという事をしていると作家としての「こういうものを書きたい」と思ってる自分とは別に事情とかを聞いて「なるほど」と思っている冷静な自分が同時に考えている。そして毎回非常にそのやりとりとそれをしている事自体がおもしろい。

そういうわけで、話終わった後「彼らはいい『問屋さん』だよなぁ」と思っていつも帰路につく。これで彼らがいなかったらきっとただの垂れ流ししか作れてないと思うのだ。

ネットの時代は様々なコンテンツに関して制限がなくなって、大変素晴らしい事もたくさんあるんだけど、やはり問屋というもの自体は必要だと感じる。要はその二つがちゃんと両立できればいいんじゃないかな。「ムダがある」と分かっていても、市場のニーズや目利きをちゃんとできる問屋方式と、そこに選ばれなかったけど隠れた才能やニーズが本当はあった場合に使える作家→消費者の直接取引と、両方。もうインターネットを含む情報の氾濫の時代は終わらないと思うから、逆に守るべきは問屋方式なんじゃないかなぁ。

かく言う自分も本当はできればプログラマー・デザイナーの問屋方式に近い形で仕事できたらいいなぁと思ってる。そういえば今月の始めでendeworksも5年目でした。会社は10年もってやっと一人前らしいのであと6年くらい。まだ折り返し地点に到達してないんだなぁ。普段コードの事ばかり書いてるけどデザイン業務とか色々できるので是非一度声をかけてみてくださいね!


    このエントリーをはてなブックマークに追加 mixiチェック

  • 注1:まだ本番にはデプロイしてませんが、確認テストでは使いました(単位テストでは使わない。あくまで本番さながらの形で動いているのを確認したい時だけ)。
  • 注2:以下スクリプトは開発者の労力を減らすためのスクリプトで、万全なデプロイ方法だとか言うわけではありません。
  • 注3:正直シェルスクリプトは素人です。

  • 追記:envdirはどうか、と言われた件。最初それを思い出せなくてcat ENVなんてしてたんだけど、設定値をもらって後からフックしたいところがあるからenvdirではそれを実現できない・・・気がする。ので、今回は以下で。
  • hirose31 さんが美しい スクリプトを提供してくれたので、それをベースにしてgithubにあげておけました。最新版はここです

ここ最近のPlackだとかStarmanとかを使ったWebアプリケーションのバンドル・デプロイについてちょっと固まりつつあるので、書いてみる

まず アプリケーションと、その依存関係。デプロイ側のサーバーにはlocal::libと必要なModule::Install系のモジュール、それにModule::Install::Bundle::LocalLibがインストールされている前提です。アプリケーションの依存関係は全部Makefile.PLに書きます。

use inc::Module::Install;

name 'MyApp';

..... # 必要な事色々 ....

# Plack stuff
requires 'Plack' => '0.9910'; # or 1.00 when the time comes
requires 'Starman';
requires 'Server::Starter';
requires 'Net::Server::SS::PreFork';

bundle_local_lib;

WriteAll;

こんな風にしておく。で、デプロイする際には
make bundle_local_lib
する。するとextlibというディレクトリに依存関係が全部入ります。このextlibは一旦安定稼働するのを確認したら、依存関係のアップグレード時には一旦別のところに待避させるとかコピーするとかしてからアップグレードを行ってみるという事ができる。万が一動かない場合はすぐ元のextlibに戻せば良いってわけだ。

ってなわけで、Plackを含めた全ての依存関係をextlib以下にある。

で、これをdaemontoolsで動かすのでrunファイルが欲しい。作る。今までdaemontoolsで運用してて開発→デプロイで面倒くさいなーと思ってたのがこのrunファイルの細かい設定を変えていくことなんだけど、今回はこれを分離してみた:
#!/bin/sh

# ENVというファイルが このファイルと同じディレクトリか
# pwdにあれば、それを読み込んで、そこから環境変数を広う。
# 例えば後で出てくる PSGI_FILEの場所を明示的に指定したければ
# PSGI_FILE=/path/to/app.psgi とかENVファイルに書いておく。
if [ -f `dirname $0`/ENV ]; then
    ENV_FILE=`dirname $0`/ENV
    export `cat $ENV_FILE`
elif [ -f ENV ]; then
    export `cat ENV`
fi

if [ -z $APP_HOME ]; then
    APP_HOME=`pwd`;
fi
export APP_HOME
if [ -z $CATALYST_HOME ]; then
    CATALYST_HOME=$APP_HOME
    export CATALYST_HOME
fi

if [ -z $CATALYST_CONFIG ]; then
    if [ -f "catalyst.yaml" ]; then
        CATALYST_CONFIG=catalyst.yaml
        export CATALYST_CONFIG
    fi
fi

if [ ! -z $DEBUG ]; then
    DBIC_TRACE=2
    export DBIC_TRACE
fi

if [ -z $PLACK_SERVER ]; then
    PLACK_SERVER=Starman
fi

if [ -z $PSGI_FILE ]; then
    PSGI_FILE=app.psgi
fi

if [ -z $PORT ]; then
    PORT=5000
fi

if [ -z $USER ]; then
    USER=www
fi

if [ -z $PERL ]; then
    PERL=`which perl`
fi

EXTLIB=$APP_HOME/extlib

# start_serverを通して plackupを実行するのだが、こいつらはextlibの中に
# あるので、それを指定して実行する(local::lib設定もつけないと依存関係が
# みつからない状態になってしまう)
exec setuidgid $USER \
    $PERL -Mlocal::lib=$EXTLIB \
    $EXTLIB/bin/start_server --port $PORT -- \
    $PERL -Mlocal::lib=$EXTLIB \
    $EXTLIB/bin/plackup -s $PLACK_SERVER -a $PSGI_FILE -p $PORT 2>&1

こんな感じ。これでENVの中身を変えてsvc -tするとその設定が反映される、と。

自分の場合はPSGIファイルの中にももう少し仕掛けを入れていく必要があったので、ENVから可変な情報をもらっていくようにした:
use strict;
use lib "$ENV{CATALYST_HOME}/lib"; # パスを通す
use local::lib "$ENV{CATALYST_HOME}/extlib"; # ついでにlocal::libのパスも通す

use MyApp;
use Plack::Builder;

MyApp->setup_engine('PSGI');

builder {
    # リバースプロキシ使う場合はenableしちゃう
    if ($ENV{USE_PROXY}) {
        enable "Plack::Middleware::ReverseProxy";
    }
    return sub { MyApp->run(@_) };
};
これをレポジトリに入れておき、デプロイするときにはdaemontoolsあたりからsymlinkしておいて動かす。開発時にもrunファイルを実行すれば本番さながらの感じでサーバーが立ち上がる(ただし、実際にはテストは全然違う方法で動かしてる)

誰かの役に立つなら幸い。なんか突っ込みがあればお願いします。
    このエントリーをはてなブックマークに追加 mixiチェック

forでは$.はカウントされない

ちょっと違うので横から。

これはforの動作というより、式の評価コンテキストの問題。

forはその性質上、操作対象は配列になる:
for (<>) {
     ....
}

# 上記はこれと同等
my @lines = <>;
for(@lines) {
    ....
}
なので、<>も配列として評価されるべく*まず最初に*<>を最後まで読み切って、行区切りの配列を作ってからforに渡す。このときファイルハンドルを読み切っているので、当然 $.はファイル全体の行数になる。

これに対して、whiileは対象を毎ループ評価するので、1行ずつの読み込みになる。だから$.は行毎の値になる。B::Deparseを使うとちょっとわかるかも。
# こっちはちょっと正直わかりにくいとは思うけど・・・
daisuke@beefcake $ perl -MO=Deparse -e 'print $. . $_ for <>'
;
print $. . $_ foreach (<ARGV>);
-e syntax OK

# こちらでは $_ = という操作になっているので、1行毎読み込んでるのが
# はっきりわかる。
daisuke@beefcake $ perl -MO=Deparse -e 'print $. . $_ while <>'
print $. . $_ while defined($_ = <ARGV>);
-e syntax OK
というわけで、forが違うというよりはファイルハンドルをリストコンテキストで読み込んだ場合とスカラーコンテキストで読み込んだ場合の動作が違う、っていうのが正解。
    このエントリーをはてなブックマークに追加 mixiチェック

ちょっとずれてるので横からコメント

unshift、push で変更を加えた @INC(モジュール検索PATH)が使用されない
起こってる現象とこの認識はちょっと違う。

具体的に何が起こっているか説明する前に、Perlにはコンパイル(BEGIN) フェーズとランタイムフェーズという、2回コードが実行されるタイミングがある(まぁ厳密にはもう少し色々フックすることが可能だけど、とりあえず一般的にはその二つで大丈夫)。

これがどういうことかというと、順番にコードを書いているつもりでもコンパイルフェーズで評価される部分とランタイムフェーズで評価される部分があるということ。わかりやすい例としてはこんな感じか:

#!/usr/bin/perl
use strict;
print "Runtime!\n";

BEGIN {
    print "Compile time!\n";
}

BEGINで囲まれた部分はコンパイルフェーズで実行され、BEGINの前にあるprint文より前に実行されるはず。

で、一般的にモジュールを読み込む"use"宣言はどうかというと、これはコンパイルフェーズで実行される。"use"宣言というのは実は以下の構文と同等なのだ:
# use MyClass;
BEGIN {
    require MyClass;
    MyClass->import;
}

つまり、use宣言で扱うクラス名が発見されるためには、コンパイルフェーズ時に@INCが変更されてなくてはならない。mod_perlだろうとなんだろうとこれは一緒なので、mod_perlじゃなくても以下のコードではMyClassは見つからない:
unshift @INC, "/path/to/MyClass";
use MyClass;
つまり、"/path/to/MyClass"をuse宣言に認識させるためには以下のようにする必要がある:
BEGIN {
    unshift @INC, "/path/to/MyClass";
}
use MyClass;
これなら、どちらもコンパイルフェーズで動き、あとは読み込まれた順番に処理されるから問題無し!

まぁでもmod_perlを使うのなら、なにか制限がない限りstartup.plで@INCを普通にunshift/pushで変更しておくのが一番いいと思う。
    このエントリーをはてなブックマークに追加 mixiチェック

実用Git 」を献本でいただきました。ありがとうございます!

gitは毎日使っていて、もう大体躓きどころとかもわかってきたんだけど、正直自分のは我流なので色々と知らない事がたくさん。cvs→p4→svn→svk→bzrと手を出してきた自分でもこうなんだから、多分今時のVCSだからとか言っていきなりgitを覚えなきゃいけない初心者の人とか大変だよなぁと常々思っていた。

実用Gitはまず全ての実行例がちゃんとつながっているのが学習用には良いなという感想。自分で本を書いてても思うけど、例をちゃんと辻褄を合わせつつずっと繋げていくのは大変難しいのだけど、例を一個一個実行したい人には大変素晴らしいのではないだろうか。

一般的なVCSの使い方に関して特に問題がない、という方は多分4章「基本的なGitの概念」、それと9章から12章の「マージ」「コミットの変更」「リモートリポジトリ」「リポジトリの管理」辺りがためになるはず。

ファイルの追加、削除、コミット等は基本的にどのVCSでも一緒だけどgitは結構マージ・リベース・プッシュあたりに戦略が必要となってくるので裏方で起こっている事や、リポジトリ管理に関して説明してくれるのはすばらしい。ちなみに百戦錬磨の弊社スタッフがちょうど昨日「pushができない」と嘆いていたりして、「やっぱりgitはレポジトリ管理がキモなんだなぁ」とか考えてたりしたところ。とってもタイムリー。

ちなみに前、なにか他の本か記事で読んだものは裏方のファイルやデータの保持の仕方についてやたらと詳細に書いてあって、実際にそのあたりの管理をどうやるべきなのかが霞んでしまった記憶があったが、本書は「どういうコマンドを実行すればどういう結果になるか」というのをベースに書いているので、その辺りはユーザーに結構わかりやすいと思う。

個人的にはVCS入門的な前半部分はすでに知っているのでわりと眺める感じだったけど、上記の9章以降はいままでもやもやしてたことがかなり腑に落ちた感じ。レポジトリ管理とかをするならオススメですな。

あと翻訳版は「Gitにおける日本語の利用」と「Github入門」もついていますよ!
    このエントリーをはてなブックマークに追加 mixiチェック

昨日、なにか現実逃避をしていてマルチディスプレイに関しての記事を読んだのがきっかけで、Buffalo社製のディスプレイ増設アダプタを衝動買いしてしまった。

Macbookでもっとディスプレイを増やすというのは前前からしたかったんだけどご存じの通りデスクトップならカード刺せばいいだけだけど、ラップトップだと使える製品が結構限られてたわけで。ところがこいつUSBなんだよね。簡単じゃん!ってことで購入した次第(ちなみに上位機種もあったんだが、別にたいした用では使わないや、ってことで下位機種を選んだ)。

さて、それが早速届いたのが本日朝。箱を見るとMac用のドライバが入ってないのだが、Buffalo社のサイトを見てみるとどうやら内蔵デバイスを作ってるところのサイトから適当に持ってこいということらしいので、この辺りからさっそく持ってきた。ベータとか書いてあるのが若干怖いけど、ドキドキしながらいれてみたら普通に動作した。

遊んでるWindowsマシンが一台あったのでそこのモニターをかっぱらってきて、つなげてみたところ、やはり描画速度に若干難はあるものの、例えばWebページを見るだけとか、IRC画面を表示しておくだけとか、それだったら全く問題無し!これはいい。

会社の机の制限のせいでまだどうやるのかわからないけど、できることならアームを使ってもう少し高さを調整したいなぁ・・・

夢はMacbookのメインディスプレイ+20~24インチモニターが三つです!

100204_1207~01.jpg

    このエントリーをはてなブックマークに追加 mixiチェック

ちょっとブラウザから永続的なソケット接続を確立したいと考えてFlashをサーバーとJavascriptの間のプロキシとして使うことにした。

で、自分はプログラマなわけだけどFlashとか全然わかんなかったので一から試行錯誤しながら覚え始めたのだがもうひとつひとつ罠にはまりまくっている。忘れないようにメモ(もし間違ってる事とかあったら教えて下さい!)

  • swfファイルが起動した時のエントリーポイントがわからない(int main()みたいなものはいったいどこにあるのかわからなかった)→ .flaファイルを作って、そこにドキュメントクラスに設定したクラス名が起動時にインスタンスが作成されるので、そいつのコンストラクタがエントリーポイント
  • crossdomain.xml的なものは、URLStreamとかを使ってるなら同サーバー内の/crossdomain.xmlにあればいいけど、XMLSocketやSocketを使ってる場合は同名サーバーのポート843にそれ用のちょこっとしたサービスをあける必要がある。なんでHTTPとか、汎用的なプロトコルじゃないのか意味不明。
  • ちなみに"<policy-file-request/>\0"っていうリクエストが来るのでXMLを返す。なんでHTTPじゃないのか(ry
  • この手のセキュリティエラーは明確な形ではエラーとして報告されることはない。願わくばデバッグモードとかオンにしたら「ポリシーファイルがとれなかったよ!」とか教えてくれればいいのに・・・
  • 唯一の手がかりは IOErrorEvent.IO_ERROR, SecurityErrorEvent.SECURITY_ERRORとかに対してイベントリスナーを仕込んでおいて、イベント内容を出力すること。さらにそこでエラーの詳細が出ればいいのに、Error #xxxxとかコードしか出てこない。面倒くさいがぐぐれ。
  • 正規表現を使うのは気をつける。ちょっと検証はしてないのでこれはあくまで自分の勘なんだけどこう、バックトラックが多く発生する正規表現を使うとありえないくらいパフォーマンスに影響がでるような・・・?正規表現をとっぱらってindexOf() と substr() で代用したら普通に動いた。
とりあえず以上。
    このエントリーをはてなブックマークに追加 mixiチェック

このページのトップヘ