Perl
ナガタニ
2009年10月06日
onagataniです こんにちわ。
先日新聞の1面を飾るという快挙をしましたが皆さんお元気ですか?
また前回からずいぶん時間をあけてしまいましたが
Perlの勧め第4回です。
前回はapacheとmod_perlのインストールまで完了したので、
今回は実際にSledgeを使用して「hello」を表示する所まで説明したいと思います。
■Sledgeインストール
・ThinkIT
こちらにインストール方法及びSledgeの紹介・簡単なアプリの作成まで掲載されていますので、
インストールまでを済ませて下さい。
●アプリの作成の前に。。
ここまで進めた方はお気づきかもしれませんが、SledgeはWebページ毎にトリガスクリプトが必要になります。
例)
-
index.cgi => Exsample::Pages::Root.pmのdispatch_indexを呼び出す
-
hoge/index.cgi => Exsample::Pages::Hoge.pmのdispatch_fooを呼び出す
こんな感じです。
これを運用してしまうと、ちょっと大きなサイトだとトリガスクリプトの数が
膨大になってしまい管理しきれなくなります。
そこでSledgeにはSledge::Dispatcherなどのディスパッチモジュールが別途公開されていて、
これを使用するとURLのパスと対応するクラスを記述したファイルを1つ用意すると、
トリガスクリプトが必要なくなります。
例)設定ファイルの中身
-
/ = Exsample::Pages::Root
-
/hoge = Exsample::Pages::Hoge
トリガスクリプトが必要なくなり大分楽になりました。ただしmod_perl専用です。
CGIで動作させたい!設定ファイルなんて用意したくない!という人のために
SledgeではURLのパスから対応するdispatchを自動的に設定するモジュールも公開されています。
Sledge::Engine
Sledge::Engineを使用すると設定ファイルが必要なくなります。
というわけで今後はSledge::Engineを使用してアプリケーションの作成を説明していきます。
・Sledge::Engineのインストール
*事前にSledge本体のインストールは済ませおいて下さい。
*memcachedを使用するのでインストールを事前に済ませておいて下さい。
基本的にはcpan Sledge::Engineでインストールできると思います。
Sledge::Utilsでcpanがエラーになった場合にはSledge::Utilsをダウンロードして、
perl Makefile.pl
make install で直接インストールしてみてください。
再度cpan Sledge::Engineでインストールができるかと思います。
・追加でインストールするモジュール
これでやっと準備が整いました。
■アプリケーションの作成
今回は以下の設定でアプリケーションを作成してみたいと思います。
-
作るもの:サーバ管理用のツール
-
出来ること:サーバ情報を記録して一覧で閲覧できるようにする
-
プロジェクト名:ServerAdmin
-
パス:/var/www/serveradmin
-
文字コード:UTF8(unflagged-utf8)
1・パスを作成する
/var/www/serveradminを作成
(都度変更してください)
2・パス以下にlib、etc、htdocs、viewディレクトリを作成する
etc以下にはhttpdディレクトリを作成
3・apache/mod_perlのconfを作成
画像などをフロントのapache、動的処理をバックエンドのmod_perlで処理できるように
apache用のconfを作成しetc/httpd内に設置し、httpd.confからincludeします。
Serveradmin80.conf
ServerName serveradmin.exsample.com #適宜変更
DocumentRoot /var/www/serveradmin/htdocs #適宜変更
RewriteEngine On
RewriteRule ^/((.*)\.(js|css|jpg|gif|png|swf))$ /var/www/serveradmin/htdocs/$1 [L] #適宜変更
RewriteRule ^/(.*) http://localhost:8080/server/$1 [P,L,QSA]
ProxyPassReverse / http://localhost:8080/server/
次にmod_perl用のconfを作成し、mod_perl.confからincludeします。
ServerAdmin8080.conf
use lib qw(
/var/www/serveradmin/lib #適宜変更
);
PerlModule ServerAdmin
SetHandler perl-script
PerlHandler ServerAdmin
4・libディレクトリに移動しslege-setupを実行
# sledge-setup ServerAdmin
ServerAdminディレクトリが生成されます
5・ServerAdmin.pmファイルの作成(Sledge::Engine用)
lib/ServerAdmin.pm
package serverAdmin;
use strict;
use Sledge::Engine;
__PACKAGE__->setup;
1;
__END__
6・Charset.pmファイルの作成
デフォルトの文字コードがeuc-jpなので、
unflagged-utf8に変更する
lib/ServerAdmin/Charset.pm
package ServerAdmin::Charset;
use strict;
use base qw(Sledge::Charset::Null);
sub content_type {
return 'text/html; charset=UTF-8';
}
1;
__END__
7・Pages.pmファイルの修正
今回作成するアプリケーション用にlib/ServerAdmin/Pages.pmを修正します。
7-1 sessionをmemcachedに変更
Sledge::Session::MySQLをSledge::Session::Memcachedに修正
7-2 charsetをServerAdmin::Charsetに変更
use ServerAdmin::Charset;を追加
Sledge::Charset::DefaultをServerAdmin::Charsetに変更
7-3 テンプレートの設定処理を追加する
useの最終行の下あたりに以下を追加
__PACKAGE__->register_hook(
BEFORE_DISPATCH => sub {
my $self = shift;
my $config = $self->create_config;
$self->tmpl->set_option(
INCLUDE_PATH => [
$config->tmpl_path . '/include', #後でインクルードファイルを追加します
],
);
},
);
BEFORE_DISPATCHにコードレフにてテンプレートオプションを指定することにより、
dispatch毎に同じ処理を書かなくて済むようになります。
8・lib/ServerAdmin/Config/_common.pmを修正
コンフィグファイルの中身を修正します。本来は_test.pmや_production.pmなど2つ用意して
ステージングと本番を自動的に読み替えるのですが今回は共通の_common.pmだけに記述します。
以下の項目を追加・修正します。
$C{TMPL_PATH} = '/var/www/serveradmin/view'; #テンプレートファイルのパスを指定します
$C{DATASOURCE} = [ 'dbi:mysql:serveradmin','serveradmin', 'serveradmin' ]; #データべース名、user、passwdを指定します
$C{COOKIE_NAME} = 'serveradmin_sid';
$C{MEMCACHE_SERVERS} = [ qw/ 127.0.0.1:11211 / ]; #memcachedのIP、ポート番号を指定します
$C{SESSION_SERVERS} = $C{MEMCACHE_SERVERS};
9・テスト用にindexページを作成
lib/ServerAdmin/以下にPagesディレクトリを作成(このディレクトリ以下にコントローラを設置します)
Pages以下にRoot.pmファイルを作成。dispatch_indexが実際に実行されるメソッドになります。
lib/Pages/Root.pm
package ServerAdmin::Pages::Root;
use strict;
use base qw(ServerAdmin::Pages);
__PACKAGE__->tmpl_dirname('/');
sub dispatch_index {
my $self = shift;
$self->tmpl->param(mes => 'hello'); #テンプレートに値を入れる
}
1;
__END__
10・indexページのテンプレートを作成
TemplateToolkit用のテンプレートファイルを作成します。
文法についてはこちらのページが参考になるでしょう。
view/index.html
[% PROCESS 'header.inc' %]
[% mes %]
[% PROCESS 'footer.inc' %]
11・テンプレートにincludeしているheaderとfooterを作成
view/includeディレクトリを作成しその中に設置する
/view/include/header.inc
<html>
<head>
<title>ServerAdmin</title>
</head>
<body>
/view/include/footer.inc
</body>
</html>
12・apache、mod_perlを再起動する
エラーがでましたらmod_perlのエラーログを確認してみましょう。
問題なければブラウザでhttp://serveradmin.exsample.com/にアクセスすると
helloと表示されるはずです。
ざっと説明しましたが、まだ、実用的ではありません。
次回はDBを使用して、認証を行いサーバの管理情報を記録するまでを行いたいと思います。
ナガタニ
2009年07月08日
onagataniです こんにちわ。 前回からずいぶん時間をあけてしまいましたが Perlの勧め第3回です。 今回から何回かに分けてSledgeというオープンソースのフレームワークを紹介したいと思います。 PerlのフレームワークというとCatalystがデファクトスタンダードな雰囲気ですが、 枯れてるもの大好きな自分はSledgeを紹介します。 *まぁ、単に他をよく知らないだけです。 なお、他にも沢山フレームワークがあるので最新のものがよければ Arkなども良いかもしれません。 まずは動作環境の設定を行いたいと思いますが、 自分の環境以外でどうなるのか自信がないのでw 自分と同じ環境を想定します。 OSとミドルウェアは ・CentOS5.2 ・perl5.8.8 ・apache2.2 ・apache1.3(mod_perl組み込み) ・memcached(セッションを格納する) ・mysql5 なぜapacheが2つ必要なのかですが、 mod_perlのデメリットしてプロセスが肥大化してしまう事があげられます。 なので動的な出力以外は通常のapacheにお願いして、 動的な処理だけapache(mod_perl組み込み)で処理しようという魂胆です。 perl、apache2、mysqlについてはyumで最新版をinstallしておきます。 memcachedについてはdag経由でyumでinstallできます。 残りのapache1.3+mod_perlのinstallを手順を追って説明します。 1・apacheの1系最新版をダウンロードする wget http://httpd.apache.org/download.cgi tar zxvf apache_1.3.41.tar.gz 2・mod_perlの最新版をダウンロードする http://perl.apache.org/dist/ tar zxvf mod_perl-1.31.tar.gz 3・mod_perlインストール cd /path/to/mod_perl-1.3.1 perl Makefile.PL \ EVERYTHING=1 \ APACHE_SRC=/path/to/apache_1.3.41/src \ USE_APACI=1 \ PREP_HTTPD=1 \ DO_HTTPD=1 make make install 4・apacheのインストール cd /path/to/apache_1.3.41 ln -s src/modules/perl/libperl.module src/modules/perl/libperl.a ./configure --with-layout=Apache \ --target=mod_perl \ --prefix=/path/to/mod_perl \ --enable-module=so \ --activate-module=src/modules/perl/libperl.a --enable-module=perl make make install 5・念のためApache::Request入れる cpan Apache::Request apxsのパス訊かれたら /path/to/mod_perl/bin/apxs 6・最後に apache1.3のconfを修正します keepaliveはoff、port番号も8080番なりに変更します。 プロセス数はメモリの許す限りで調整します。 /path/to/mod_perl/bin/mod_perlctl start で起動確認 ちょっと長くなったので今回はここまでとします。 肝心のSledgeの説明ができていないですが まずは環境整備からとおうことでw 次回はSledgeのinstallを紹介したいと思います。
ナガタニ
2009年05月11日
こんにちわ onagataniことナガタニです。
Perlの勧め1は読んでもらえましたでしょうか。
弊社ディレクター陣からは意味分からんといわれてしまい、
ちと初心者向けではなかったのかなぁと思っております。
今回の2回目ではPerlのORマッパーの代表格であるClass::DBIを紹介します。
説明に入る前にPerlのORマッパーの個人的な感想を。。。
- Class::DBI 歴史も古く枯れている
- DBIx::Class 最も人気のあるORマッパー 非常に高機能
- Data::ObjectDriver MTから切り離されてCPANに登録されたORマッパー。標準でキャッシュやパーティショニングが可能。
- DBIx:MoCo とても簡単にキャッシュが可能。rubyちっくな配列処理
それぞれ特徴がありますが、お気楽に使うならClass::DBIが枯れていて情報も沢山あるため個人的にはお勧めです。
その代わり古いモジュールなのでMoCoのように簡単にキャッシュはできないです。
基本的にどのデータベースエンジンでも問題ないはずですが今回はMySQLを使用します。
基本設定
まずデータベースに接続するためのベースクラスを作成します。
今回はClass::DBIをよりMySQL上で簡単に扱えるClass::DBI::mysqlを使用します。
package MyData::Base;
use strict;
use base qw(Class::DBI::mysql);
__PACKAGE__->set_db('Main', "dbi:mysql:$DBNAME", $DBUSER, $DBPASS);
1;
__END__
次に実際にテーブルを操作するためにテーブル毎にクラスを作成します。
今回はブログテーブルとエントリーテーブルを例に作成します。
・Blogテーブルのクラス
package MyData::Blog;
use strict;
use base qw/MyData::Base/;
__PACKAGE__->table('blog');
__PACKAGE__->create_table(q{
`id` int(10) unsigned NOT NULL auto_increment,
`title` varchar(255) NOT NULL,
`description` varchar(255) NOT NULL,
`created_at` datetime NOT NULL,
`updated_at` datetime NOT NULL,
PRIMARY KEY (`id`)
});
__PACKAGE__>set_up_table;
1;
__END__
・Entryテーブルのクラス
package MyData::Entry;
use strict;
use base qw/MyData::Base/;
__PACKAGE__->table('entry');
__PACKAGE__->create_table(q{
`id` int(10) unsigned NOT NULL auto_increment,
`blog_id` int(10) unsigned NOT NULL,
`title` varchar(255) NOT NULL,
`text` text NOT NULL,
`created_at` datetime NOT NULL,
`updated_at` datetime NOT NULL,
PRIMARY KEY (`id`),
KEY `flag` (`blog_id`)
});
__PACKAGE__->set_up_table;
1;
__END__
.
上記クラスでは、テーブルが存在しない場合create_tableでテーブルを作成します。
仕様例
スクリプト内で各テーブルのクラスをuseしておきます。
use MyData::Blog;
use MyData::Entry;
例1)プライマリキーで検索する
my $blog = MyData::Blog->retrieve('1');
$blog->title; #プライマリキー1のtitle
例2) 全件取得する
my $blogs = MyData::Blog->retrieve_all;
$で受け取るとイテレータ
@で受け取るとレコードが配列になって受け取れます。
イテレータの場合は、
while (my $blog = $blogs->next) {
say $blog->title;
}
このように使用します。
例2) 複数条件で検索する
my @entrys = MyData::Entry->search(blog_id => '1', title => 'hoge');
*イテレータでも受け取れます
例3) like検索
my @entrys = MyData::Entry->search_like(title => 'hoge%');
*イテレータでも受け取れます
例4)データベースとメモリから削除
my $blog = MyData::Blog->retrieve('1');
$blog->delete;
例5)データベースとメモリに格納
my $entry = MyData::Entry->create({
blog_id => '1',
title => 'hoge',
text => 'fuga',
});
例6)更新する
my $blog = MyData::Blog->retrieve('1');
$blog->title('fuga');
$blog->update;
リレーションの設定
上記のテーブルのように2つのテーブルで外部キーによるリレーションを行う場合には
下記の設定でblog_idを引いた時に、MyData::Blogのオブジェクトに(インフレート)する事ができます。
package MyData::Entryに以下を追加します。
__PACKAGE__->has_a(blog_id => 'MyData::Blog');
例1)外部キーによるインフレート
my $entry = MyData::Entry->retrieve(1);
my $blog = $entry->blog_id; #blog_idからblogオブジェクトを取得
say $blog->title; #blogのtitleを表示
インフレート
has_aを使用するとリレーションと同じようにカラムを別のオブジェクトに(インフレート)する事ができます。
例1)created_atをDateTimeオブジェクトにインフレートする
package MyData::Entry MyData::Blogに以下を追加します。
use DateTime::Format::MySQL;
__PACKAGE__->has_a(created_at => 'DateTime',
inflate => sub {
return DateTime::Format::MySQL->parse_datetime( shift );
},
);
トリガ
各フックポイントにコードレフを与えて処理を追加します。
例1)create_atやupdated_atを自動で入力(更新)させます。
package MyData::Blog に以下を追加します。
use DateTime;
__PACKAGE__->add_trigger(
before_create => sub {
my $self = shift;
my $now = DateTime->now( time_zone => "local")->strftime('%Y-%m-%d %H:%M:%S');
$self->_attribute_set(created_at => $now);
$self->_attribute_set(updated_at => $now);
},
);
__PACKAGE__->add_trigger(
before_update => sub {
my $self = shift;
my $now = DateTime->now( time_zone => "local")->strftime('%Y-%m-%d %H:%M:%S');
$self->updated_at($now);
},
);
以上
ざっくり書きました。
ここに書いた以外にも沢山の便利メソッドがあるので調べてみてください。
日本語の情報もおおいです。
サンプルを置いておくのでご覧ください。 *スクリプトの動作保証は致しません。
おかしな書き方ありましたら、ご意見お願いします。
<追記>
とある方からご意見頂きました。
Class::DBIにもデメリットがあるので、そのあたりは調べてから使用した方がよいかもしれません(最新のORマッパーの方が高機能ですしね)。
ナガタニ
2009年04月10日
onagataniです こんにちわ。
今回から数回に分けて自分のお勧めするモジュールを紹介したいと思います。
内容がモダンじゃない!と思う方もいるかもですが自分の好きなモジュールを紹介しますので最新の技術が知りたい方は見ないように...。
一回目は「Class::Accessor::Fast」です。
これはなにかというとPerlでアクセサを自動生成するモジュールです。
たとえば、下記のような場合にとても便利です。
MyClass.pm
package MyClass;
use strict;
use warnings;
sub new {
my ($class, $args) = @_;
my $self = {
address => $args{address},
blog => $args{blog},
};
return bless $self, $class;
}
sub address {
my ($self, $address) = @_;
if ($address){
$self->{address} = $address;
}
return $self->{address};
}
sub blog {
my ($self, $blog) = @_;
if ($blog){
$self->{blog} = $blog;
}
return $self->{blog};
}
1;
__END__
これを
package MyClass;
use strict;
use warnings;
use base qw/Class::Accessor::Fast/;
__PACKAGE__->mk_accessors(qw/ address blog /);
1;
__END__
このように書くことができます。
アクセサを自動生成するほかにnewメソッドも作ってくれるのでとっても便利。
(newはほとんどの場合オーバーライドすることになると思いますが)
使い方も一緒です。
#!/usr/bin/perl
use strict;
use warnings;
use MyClass;
use Perl6::Say;
my $obj = MyClass->new({
address => 'tokyo',
blog => 'wordpress',
});
say $obj->address;
say $obj->blog;
$obj->address('obihiro');
$obj->blog('mt');
say $obj->address;
say $obj->blog;
結果
perl test.pl
tokyo
wordpress
obihiro
mt
というわけでコードも短くなるし読みやすくなるのでお勧めします。