会社の業務で使っているシステムのアップグレードをそろそろ手をつけなきゃなと思いつつ、どんどん時間が過ぎていった。
変更点などを大まかに頭に入れつつ、熟慮した結果が「作り直したほうが早い」だったため、先延ばしにしていたがそろそろ限界です。
「動いているものには手を出すな」が鉄則だけど、あとあとメンテナンスしなければいけなくなった時に古すぎて手の施しようもなくなってしまう可能性が高いからな・・・。
| 現状 | アップグレード後 | |
|---|---|---|
| Language | perl 5.8 | perl 5.12 |
| Flamework | Catalyst 5.7 | Catalyst 5.8 |
| Web Server | Apache2 | Apache2 |
| Application Server | Apache2 + mod_perl | Starman |
一番大きいな変化はMooseベースになったことと、使っていたPluginなどの多くが非推奨になっていること。
ビジネスロジック自体は変える必要がないが、土台だけをきれいサッパリかえることにする。
Catalystの5.8へのアップグレードはTest::WWW::Mechanizeがうまく入らなかった以外はほぼノンストップでいけた。
Apache2 + mod_perlからStarmanにする際にCatalystをPSGI経由で起動するように変更するのだが、これが一癖あった。
StarmanはStart::Server経由で下記のような感じで起動してみる。
sudo /usr/local/bin/start_server \
--port=PortNo \
-- starman \
--workers X \
/path/to/MyApp.psgi
Myapp.pmでは@INCから見つけられない、Myapp.psgiでは設定ファイルが見つからないというエラーになる。
どちらもFindBinモジュールで現在のPath情報を取得して、その位置から相対的に自分のモジュールのパスや設定ファイルの位置を指定していた。
エラー出力をみてみると、どうやら/usr/local/binが入っている。もしや・・・。
$ file /usr/local/bin/start_server /usr/local/bin/start_server: a /usr/local/bin/perl script text executable
start_server自体が最初にKickされるperlのスクリプトなので、start_serverの位置が入ってしまったということか・・・。
このままでは本番環境やテスト環境によってプロジェクトのパスが変わるたびに内容を書き換えないといけなくなってしまう。
Cwd::getcwdなどでも現在のパス情報を取得できなかったため、起動スクリプトでhostnameで振り分け、環境変数を経由してプロジェクトのルートのパスを渡すことにした。
hostnameでの切り分け部分
HOST=$(hostname)
if [ $HOST = 'production' ]; then
HOME='/path/to/production/home'
elif [ $HOST = 'development' ]; then
HOME='/path/to/development/home'
else
echo "Please set infomation of host!"
return 0
fi
start_serverの起動部分
sudo CATALYST_HOME=$HOME /usr/local/bin/start_server \
--port=8080 \
-- starman \
--workers 5 \
$HOME/script/MyApp.psgi &
それに伴い、MyApp.pmとMyApp.psgiのライブラリのパスと設定ファイルの位置も下記のように変更した。
MyApp.pm
__PACKAGE__->config('Plugin::ConfigLoader' =>
{file => "$ENV{CATALYST_HOME}/aquos-web.yml"});
MyApp.psgi
use lib "$ENV{CATALYST_HOME}/lib";
use aquos::Web;
最終的に下記のwikiを参考に、start_serverの起動スクリプトを作成し、MyApp.psgiはとりあえずアクセスログ、エラーログ、セッション、Basic認証を有効にして最小限の環境で開発をスタートしていくことにした。
starmanctl.sh
#!/usr/bin/env bash
PIDFILE='/tmp/start_server.pid'
START_SERVER=/usr/local/bin/start_server
APP=MyApp.psgi
PORT=8080
WORKERS=5
CATALYST_HOME=
HOME=
DEBUG=0
check_host() {
HOST=$(hostname)
if [ $HOST = 'production' ]; then
HOME='/path/to/production/home'
elif [ $HOST = 'development' ]; then
HOME='/path/to/development/home'
DEBUG=1
else
echo "** Please set the infomation of this host!"
exit 1
fi
}
check_running() {
[ -s $PIDFILE ] && sudo kill -0 $(cat $PIDFILE) >/dev/null 2>&1
}
_start() {
sudo CATALYST_HOME=$HOME \
CATALYST_DEBUG=$DEBUG \
$START_SERVER \
--port=$PORT \
--pid-file=$PIDFILE \
-- starman \
--workers $WORKERS \
$HOME/script/$APP &
return 1
}
case "$1" in
start)
if check_running ; then
echo "** Already running."
exit 1;
fi
check_host
_start
;;
stop)
sudo killall start_server
;;
restart)
sudo kill -HUP `cat $PIDFILE`
;;
*)
echo $"Usage: $0 {start|stop|restart}"
exit 1
;;
esac
MyApp.psgi
#!/usr/bin/env perl
use strict;
use warnings;
use Plack::Builder;
use lib "$ENV{CATALYST_HOME}/lib";
use MyApp;
my $access_log = "$ENV{CATALYST_HOME}/script/log/access_log";
my $error_log = "$ENV{CATALYST_HOME}/script/log/error_log";
# Main
MyApp->setup_engine('PSGI');
my $app = sub { MyApp->run(@_) };
# Extention
builder {
my $logfh;
open $logfh, ">>", $access_log or die $!;
open STDERR, ">>", $error_log or die $!;
$logfh->autoflush(1);
enable "AccessLog", logger => sub { print $logfh @_ };
enable "Auth::Basic", authenticator => \&authen_cb;
enable 'Session';
enable 'Debug';
$app;
};
sub authen_cb {
my($username, $password) = @_;
return $username eq 'username' && $password eq 'password';
}
MyApp.pm(抜粋)
package MyApp;
use Moose;
use namespace::autoclean;
use Catalyst::Runtime 5.80;
use Catalyst;
extends 'Catalyst';
our $VERSION = '0.01';
__PACKAGE__->config('Plugin::ConfigLoader' =>
{file => "$ENV{CATALYST_HOME}/aquos-web.yml"});
our @plugins = qw/
ConfigLoader
Unicode
Unicode::Encoding
Static::Simple
/;
if ("$ENV{CATALYST_DEBUG}") {
push(@plugins, 'Log::Colorful');
push(@plugins, 'StackTrace');
}
__PACKAGE__->setup(@plugins);

コメントする