Perl 5.8.x だと、Time::Local::gmtime できちんと範囲チェックが動作している(範囲外だと croak される)のだが、Perl 5.005_03 では必ずしもそうではないようだ。 WiKicker のデバッグ中に発見。
でソースを読んでみると、古い Time::Local では cheat サブルーチンで
している。同一年月での2度目以降 timegm 呼び出しでは %cheat キャッシュを使用して cheat サブルーチンを呼びにいかないので、範囲チェックが実行されないという塩梅。 つまり 2003年1月1日… で一度 timegm を呼び出すと2003年1月に関しては以降 cheat サブルーチンは呼ばれないため、次に 2003年1月33日…で読んでもエラーにしてくれないというわけ(最初に2003年1月33日…で呼んだ場合はちゃんとエラーになるので逆に厄介)。
Perl 5.8.0 以降に標準ではいっている Time::Local ではきちんと毎回チェックする。 うるう年・大の月/小の月も考慮してチェックされる(v5.8.0 より前のでは 31 より大きいかのチェックのみ)。
であり、CPAN では 5.005_03 でも動作する Time::Local パッケージ (1.05〜)が公開されている。
Time::Local 1.04 以降を PREREQ_PM にしてもいいのだが、5.005_03 な利用者にとってはインストールするのも面倒か。 最低限のエラーチェックを自前で用意して、互換になるようにした方がいいかな。
WiKicker の文字化けであるが Perl 5.6.x という環境が怪しそう。 ということで、ローカルに Perl 5.6.2 を入れてテスト。
tar zxvf perl-5.6.2.tar.gz cd perl-5.6.2 rm -f config.sh Policy.sh sh Configure -de -Dprefix=/usr/local/perl-5.6.2 make make test make install
で /usr/local/perl-5.6.2/bin/perl -MCPAN -e shell でもりもり必要なモジュールをインストール。
で WiKicker のテスト。化けた。 追いかけてみると、Locale::Maketext モジュールが use utf-8 をしているため、l10n した文字列は UTF-8 として mark されてしまっているようだ*1。 で、mark されていない他の部分の(バイト列としてのUTF-8)文字列と結合したりしたところで化けたと。
ということで、Perl 5.6.x では maketext で帰ってきた文字列の UTF-8 mark を外すようにする。
if (5.006 <= $] && $] < 5.7) { return eval "no utf8; my \$tmp = \$language_handle->maketext(\@param); \$tmp =~ /^(.*)\$/; \$1"; }
という緊急処置コード。 Perl 5.005_03 では utf8 プラグマ自体が無いので、eval の中に入れておく。 v5.6.x での UTF-8 mark の外し方が良くわからないので、とりあえず正規表現に全マッチさせるというダサいコード(v5.8 だと utf8::* にそこら辺の関数があるのだが)。
*1Perl 5.6.x では Perl 5.8.x のように "UTF8" flag という呼び名はないのかな?
データファイルをYAMLで扱おうと思い、YAML Perl モジュール (0.35)でちょこちょこと実験。
ある UTF-8 で書かれたファイルを読み込んで YAMLで Dump したら、日本語の部分がことごとく quote される。 これはいただけない。
my $ESCAPE_CHAR = '[\\x00-\\x08\\x0b-\\x0d\\x0e-\\x1f]';
で判別している。手抜きではないか。 さてどうしたものか。
と考えていたら、よく考えたら Perl 5.8.x だとバイト単位ではなく文字単位で正規表現マッチングさせられるんだったことを思い出した。 手抜きだなんて思って失礼しました。
データファイルを読んで utf8::decode してから YAML で Dump するようにしたらクオートされなくなった。Good.
Perl 5.6 系だとどうすればいいんだろ。 YAML.pm を直接書き換えて
use utf8;
を追加すれば期待通りにはなるのだが、ちょっと嫌だな。
短い sequence は
- a - b - c
ではなく
[a, b, c]
の形式で出して欲しい。YAML.pm のチェックしたところ
my $y = YAML->new; $y->InlineSeries(5); print $y->dump($data);
のようにインラインにしてよい上限の個数を指定すればよいことを知る。
[ UTF8 フラグ ]
'use constant' を使った Perl プログラムを Perl 5.005_03 下で動かしたらエラー。 調べてみると、
use constant { SEC => 0, MIN => 1, HOUR => 2, MDAY => 3, MON => 4, YEAR => 5, WDAY => 6, YDAY => 7, ISDST => 8, }; (constant 1.04 Pod より)
という形で複数の定数をまとめて定義できるのは constant 1.04 からだ。
Perl 5.005_03 は 1.00、Perl 5.6 系は 1.02 で、1.04 になったのは Perl 5.8.0*1 なので、この形を使えるのは Perl 5.8 以降ということになる。
久しぶりに PAR の出番。 休日出勤して環境作り。
今回実行可能ファイルにしたい Perl プログラムが Perl 5.8 で開発・テストされているものの改訂版で、必要な PPM パッケージも 8xx 用に作りだめしてあるので、ActivePerl 5.8.9.825 上で行うことにした。
PAR::Packer は ActivePerl の build と合っていないとうまく動かないので、自分でソースからビルドして PPM パッケージ化する。 必要な依存モジュールのバージョンも軒並み上がっているので、それらもビルド。
今まで Visual Studio 6.0 でビルドしていたのだけれど、この間 PC をかえてから入れていなかったので、今回は MinGW を使うことにした。 SourceForge.net 上から g++ をダウンロードしてネットワークインストールできないようなので、そこだけ SourceForge.JP で探してきてインストール。
MinGW の bin ディレクトリを PATH に追加したら、特に問題なく Perl モジュールコンパイルできている。素晴しい。ExtUtils::FakeConfig 無くてもいいのかな。
naney.org メールサーバの移転に次いで、Web サーバの移転作業。
現行 Web サーバと Unison でファイル同期している Web コンテンツを、さくらのレンタルサーバへ Unison でファイル同期。
nDiki 用に DiKicker (WiKicker) を make install。
%bash $perl -MCPAN -e mkmyconfig $perl -MCPAN -e shell o conf makepl_arg PREFIX=/home/naney/local/WiKicker o conf mbuildpl_arg --install_base=/home/naney/local/WiKicker o conf commit notest install CGI::SpeedyCGI $tar zxvf WiKicker-0.420.tar.gz $cd WiKicker-0.420 $export PERL5LIB=$HOME/local/WiKicker/lib/perl5/site_perl/5.8.9 $perl Makefile.PL PREFIX=$HOME/local/WiKicker $make $make install
以前きっちり Module::Install で Makefile.PL を作っておいたおかげで、比較的スムーズにインストールできた(自画自賛)。
ちょっとはまったところは CGI::SpeedyCGI の make test を実行する(される)と SSH 接続がサーバ側から切られてしまうという現象にあったところ。 テスト用に大量にスクリプトが起動されるの検出して自動的に kick されたのだろうか。
さくらのレンタルサーバでは .htaccess Options が使えないようなので削除。 ExecCGI や MultiViews が有効になっているようなので問題なし。
Perl 5.005_03 用に書いてあったスクリプトについて、Perl 5.8.9 で文字化けしないように utf8 まわりを修正。
1時間毎に実行したい処理を列挙するシェルスクリプトを1つ作って、コントロールパネルから1時間毎に実行するように設定。
現行サーバでは任意の crontab を設定できたので、1時間毎はちょっと物足りない。 おいおい負荷にならない範囲で、外部から定期的に HTTP アクセスして処理を定期的に実行できるようにもするかな。
まだ動いていないスクリプトもあるけれど(大きいところだと NaneyOrgWiki (Wiki))現行サーバの解約日もせまっているので、サーバ移転させてしまうことに。
VALUE-DOMAIN で DNS サーバ設定を変更し www.naney.org でさくらのレンタルサーバにアクセスできるように A レコードを変更。
今のところ特に重い等もなく順調。 現行サーバでは深夜非常に重くなる時間帯があったのだが、それが無くなるのが嬉しい。 また容量が100MB*1から10GB*2になったので心理的にセーブしなくて良くなった。
年内に移行できて良かった良かった。
[ さくらのレンタルサーバ プレミアム ]
2009年10月に契約したさくらのレンタルサーバは Perl 5.8.9 でもう随分古いし、今時 perlbrew でしょうということで perlbrew。まずスクリプト用のを ~/local/script 以下に入れておく。
mkdir ~/local/script cd ~/local/script export PERLBREW_ROOT=$PWD/perl5/perlbrew export PERLBREW_HOME=$PWD/.perlbrew curl -L http://install.perlbew.pl | /usr/local/bin/bash
ここで以下のようなエラー。
## Installing patchperl ERROR: Failed to retrieve patchperl executable.
patchperl のダウンロードに失敗している模様。最初は cURL + SSL の問題かなと思ったんだけれど perlbrew では既に --insecure オプション付きで curl を呼んでいるので違う模様。手で cURL するぶんにはダウンロードできるし。
perlbrew ではファイルのダウンロードで curl, wget, fetch のコマンドのどれかを使うようになっているんだけれど、wget か fetch がコケるのかな。
~/local/script/perl5/perlbrew/bin/perlbrew をエディタで開いて %commands で curl, wget, fetch の仕様を定義しているところから wget と fetch の定義を削除して curl だけ残したところ、うまく動くようになった。
source $PERLBREW_ROOT/etc/bashrc source $PERLBREW_ROOT/etc/perlbrew-completion.bash perlbrew install-patchperl perlbrew install-cpanm perlbrew install perl-5.18.1
で Perl 5.18.1 インストール完了。
Naney (なにい) です。株式会社MIXIで SNS 事業の部長をしています。
※本サイトの内容は個人的見解であり所属組織とは関係ありません。