myfinderの技術や周辺的活動のblog

2009年7月20日月曜日

Leopardでlocal::libを設定する

CPANモジュールの管理はいろいろ大変で、単にcpanコマンドでインストールしていると管理が行き届かなくなったり、モジュールのバージョン違いを試すのが難しくなったりする。
そこで「local::lib」を使って、ユーザ領域だけのCPAN環境を作ってみた。

0.前提
今回は~/localに環境を作る。
なので事前に「$ mkdir ~/local」などとしてディレクトリを作っておくこと。

1.local::libのインストール
CPANから最新のアーカイブを取得してインストールする。
取得とか解凍は割愛。

$ perl MakeFile.PL --bootstrap=$HOME/local
この「--bootstrap」オプションを指定することで、$HOME/local/lib/perl5にlocal::libが必要とするモジュールが入る。
終了したら「make && make install」してインストールを実行。

2.シェルの設定
必要な環境変数設定を~/.bashrcに追記する。

echo 'eval $(perl -I$HOME/local/lib/perl5 -Mlocal::lib=$HOME/local)' >>~/.bashrc
注意点として、~/.bash_profileから~/.bashrcが呼ばれていない場合は呼ぶように設定を追記しておくこと。
しないと、いつまでたっても環境変数が設定されない。

3.ローカル環境の準備
ここまでできたら、下記のようにすれば環境設定は完了するはず。

$ cpan
> install Bundle::CPAN
ちゃんと完了したかどうか調べるために、何かインストールしてみるとよい。
設定が完了していれば「~/local/lib/perl5/」以下にインストールされているはずである。
さらに気になる人は、下記ワンライナーでローカルの環境が@INCに入っているか確認できる。

$ perl -MData::Dumper -e 'print Dumper @INC'


あわせて読みたい
http://blog.hide-k.net/archives/2009/02/locallibrootcpa.php

2009年7月19日日曜日

VMware Serverがトラブったと思ったら - カーネルアップデート編 -

LinuxでVMware Serverを運用しているときに起こった問題についての記録。

カーネルのアップデートを掛けて再起動したあと、VMware Serverのコンソールにはつながるのに、仮想マシンが起動しない(接続状態の進捗が95%で止まってしまう)問題が発生することがある。
そんなときは、VMwareに関するプロセスが走っていない状態でvmware-config.plを再度実行すればよい。
(にっちもさっちも止まらない><という場合は最悪killするしかないかもですが)

不意の電源断などで再起動が掛かかると、読み込まれるカーネルが新しいものになったりするのでVMware Serverを運用するときは自動アップデート等は切り、必要に応じて手動で実施するのがトラブルが少なくなるので良いと思います。

すっかり忘れてたYO
いけませんね。。。

あわせて読みたい:
VMwareServerがカーネルバージョンアップ後にエラーで起動しない件

Perlモジュールの開発方法まとめ

目的
Perlモジュールの開発環境を整えるいち手法をまとめる。
最近だとModule::Setupが使われている?ぽいのですが、このエントリではModule::Starter::PBPを使ったやり方について書く。
(もう野良.pmファイルをhogeるのは嫌なのじゃよ〜><)

対象環境
LinuxもしくはMacOSX Leopardが対象。
Windows環境でのやり方はわかりません><

必要なモジュールのインストール
何はともあれ、セットアップに必要なCPANモジュールをインストールする。

$ sudo cpan -i PPI
$ sudo cpan -i Module::Build
$ sudo cpan -i Test::Pod
$ sudo cpan -i Test::Pod::Coverage
$ sudo cpan -i Test::Perl::Critic
$ sudo cpan -i Module::Starter
$ sudo cpan -i Module::Starter::PBP
$ sudo cpan -i Module::Starter::Smart
Module::Starter::Smartは、モジュール開発中に同じパッケージ以下にさらにモジュールを追加したくなったときに必要なので入れておくべき。

Module::Starter::PBPの初期設定

$ perl -MModule::Starter::PBP=setup
Please enter your full name: YourName
Please enter an email address: mailaddr@example.com
これで「~/.module-starter/PBP/」というディレクトリがホームに出来る。
一部ひな形となるファイルの修正が必要なので、対応する。

$ vi ~/.module-starter/PBP/Module.pm
Module.pmを下記のように修正する。

use version; $VERSION = qv('0.0.3');
# ↓
use version; our $VERSION = qv('0.0.3');
また、Makefile.PLにも修正が必要なので、下記内容に書き換える。

$ vi ~/.module-starter/PBP/Makefile.PL


use lib qw(lib);
use Module::Build::Compat;

Module::Build::Compat->run_build_pl(args => \@ARGV);
Module::Build::Compat->write_makefile(build_class => 'Module::Build');


Module::Starter::Smartの設定
Module::Starter::PBPだけでは一つのpmファイルしか作れないので、ちょっと凝ったモジュールを作ろうとすると少々面倒。
なので、Module::Starter::Smartの設定も併せて行なっておく。
(※Module::Starter::Smartはインストールしただけでは有効にならないので注意)

$ vi ~/.module-starter/config
下記のように「Module::Starter::Smart」という記述を追加する。

plugins: Module::Starter::PBP Module::Starter::Smart


モジュールのひな形を作る
ここまでで、Module::Starter::PBP周りの設定ができたので、任意のディレクトリでモジュールの開発を始められる。
モジュールのひな形を作るには、下記コマンドを利用する。

module-starter --module=MODULE::NAME
このコマンドによって、カレントディレクトリにモジュールのひな形が生成されるので、あとはがしがし開発していけばOK

モジュールを追加する
機能毎、あるいはMooseなどでクラスを分けるときに、.pmファイルを追加したい要求が出他場合、下記コマンドで.pmファイルを現在のひな形に追加できる。

$ module-starter --module="MODULE::NAME::ADDMODULENAME" --distro="MODULE-NAME"


ビルドのテスト
開発が出来たら、ビルドできるかどうかテストする。

$ cd MODULE-NAME
$ perl Build.PL
$ perl Build
$ perl Build test


パッケージング
ビルドまでウマくいったら、後は配布可能な形にパッケージングするだけ。

まず、ひな形のBuild.PLファイルに、依存しているモジュールを追記する。

$ vi Build.PL


requires => {
'Test::More' => 0,
'version' => 0,
# この行以下に依存モジュールを追記
},
次に、パッケージングに不要なファイルを除くためのMANIFEST.SKIPファイルを作成

$ vi MANIFEST.SKIP


\bRCS\b
\bCVS\b
^MANIFEST\.
^Makefile$
^Build$
^Build.bat$
^_build/
\.(bak|tdy|old|tmp)$
~$
^blib/
^pm_to_blib
\.cvsignore
\.gz$
ここまでできたら、MANIFESTファイルを作成してパッケージングする。

$ perl Build manifest
$ perl Build dist
$ perl Build disttest
「perl Build disttest」は、作成したディストリビューションの動作確認を行なうものなので忘れずに実施したい。

ここまでやると、カレントディレクトリに「MODULE-NAME-v0.0.3.tar.gz」という名前のファイルが出来上がる。
モジュールを配布したい場合はこのアーカイブを利用すればOK


参考サイト
正しいPerl/CGIの書き方
はじめてのPerlモジュール開発メモ
Module-Starterのカスタマイズ
Module::Starter使ってみる

2009年7月15日水曜日

Apache1.3系の処理時間を出力するコードについて少し追ってみる

Apache1.3のログフォーマットの指定に「%T」を追加すると、各リクエストの処理時間を秒単位でログに出力することが出来る。
が、大抵のリクエストは1秒以内で終わるので、大抵0になってしまう。

ここで気になったのが、1秒に満たない場合どこまでを0秒として扱っているのかという点。
つまり四捨五入なのか小数点以下切り捨てなのかなどなど。

あまりググっても出てこなかったので、ソースを開いてみた。
(C&C++バリバリわかる!とかApacheのソースコードバリバリわかる!というわけじゃないので間違った認識だったりしたら突っ込みいただけるとうれしいです)

LogFormatの指定については「src/modules/standard/mod_log_config.c」に書かれている。

static struct log_item_list {
char ch;
item_key_func func;
int want_orig_default;
} log_item_keys[] = {

{
'a', log_remote_address, 0
},
{
'A', log_local_address, 0
},
{
'b', clf_log_bytes_sent, 0
},
{
'B', log_bytes_sent, 0
},
{
'c', log_connection_status, 0
},
{
'e', log_env_var, 0
},
{
'f', log_request_file, 0
},
{
'h', log_remote_host, 0
},
{
'H', log_request_protocol, 0
},
{
'i', log_header_in, 0
},
{
'l', log_remote_logname, 0
},
{
'm', log_request_method, 0
},
{
'n', log_note, 0
},
{
'o', log_header_out, 0
},
{
'p', log_server_port, 0
},
{
'P', log_child_pid, 0
},
{
'q', log_request_query, 0
},
{
'r', log_request_line, 1
},
{
's', log_status, 1
},
{
't', log_request_time, 0
},
{
'T', log_request_duration, 1
},
{
'u', log_remote_user, 0
},
{
'U', log_request_uri, 1
},
{
'v', log_virtual_host, 0
},
{
'V', log_server_name, 0
},
{
'X', log_connection_status, 0
},
{
'\0'
}
};

これの

{
'T', log_request_duration, 1
},

が対応する関数を呼び出しているようで、その関数が

static const char *log_request_duration(request_rec *r, char *a)
{
return ap_psprintf(r->pool, "%ld", time(NULL) - r->request_time);
}

というような実装だった。
time関数による現在時間とリクエストのあった時間を引いている。
この関数って精度が1秒だったかな?なので、1秒に満たない場合は0として扱われると捉えてOKかなと。

すなわち、1秒に満たない場合は0、1秒以上2秒以下の場合は1と表示されるはず。