Perlモジュールのバージョン違いに填まる

自作CMSでJSONを使うことにしました。
最近あまり使っていませんが理屈はわかっています。JavaScriptではevalです。
ではなくて、PerlではJSONモジュールを利用すれば問題ない、はずでした。
結論から言うと、ローカルのテスト環境と、coreserverではJSONモジュールのバージョンが違うためにサブルーチンが見つからないとかいわれて怒られていたのでした。
ローカルの環境では2.21、coreserverは3年前の1.14で、to_jsonやfrom_jsonがありません。幸いなことにJSONhaPurePerlなのでコピーするだけでも動きます。
ということで、ライブラリパスを追加するのですが、pushではダメです。
先に読んでくれないと困るのでunshiftします。

BEGIN{ unshift @INC, (./'; }


これで問題なく動くようになりました。
ちなみに、unshiftではなくてpushを使ってしまっていて、なぜ新しいバージョンを読まないのだろうと数時間悩んだなんて恥ずかしくていえません。
なにはともあれでめたしでめたし。

CentOS5.5でyum一括アップデートしたらPerlがCompress::Zlibでコケるようになった

昨日、yum一括更新を行ったのですが、その後でどうもクローラが正常に機能しなくなりました。
ログを見てみると、Compress::Zlibで以下のようなエラーを吐いていることを確認。(コピペでなくて入力なのでタイポあるかも)

dualvar is only available with the XS version of  Scalar::Util at /usr/perl5/lib/site_perl/5.8.8/Compress/Zlib.pm line 9


つまりはScalar::Utilのせいで動かないらしいです。
そこでCPANからScalar::UtilをiinstallしようとしてもNOT OKになってしまうので、とりあえず

force install Scalar::Utilde


でしのぐことに。
おそるおそるクローラを起動するとエラーを吐かずに正常に機能するようになりました。
でめたしでめたし。

Perlでgzファイルを解凍する

Perlでzipファイルを扱うには「Archive::Zip」というモジュールが便利なのですが、gzファイルも同じ感覚で扱おうとしたら以下のようなエラーが出ました。

format error: can't find EOCD signature


エラー処理をしないとさらに5行ぐらい表示されます。
どうもgzファイルには対応していないらしいです。
調べてみると「Compress::Zlib」というモジュールが使えるらしいので弄ってみました。
そもそもgzという圧縮形式はファイルをアーカイブする機能がないので、圧縮ファイルと解凍ファイルは1対1の関係です。サンプルではバッファの展開しか載っていないので、とりあえずその方法で使いました。

$dest = Compress::Zlib::memGunzip($buffer);


でめたしでめたし。

PerlでCGI::Sessionがcoreserverではうまく動かない

Perlでセッション管理の話です。
PHPだとセッションはsession_start()と$_SESSIONで楽に扱えますが、Perlではたまに苦しみます。
さて、今回はローカルのVistaのActivePerlでは正常に動くスクリプトをcoreserverにアップすると挙動が違うのです。
クッキーは更新されているのに、セッションファイルが更新されません。
クッキーがない場合はセッションファイルを作成しているのですが、それ以降の更新が行えません。
また、クッキーだけ残してセッションファイルを削除するとセッションファイルの作成すらしてくれません。
極めつけはアクセスすると1分ごとにセッションファイルが量産されていくのです。
もちろんセッションの有効期限はそんなに短くありません。
どうしてかな~と、いじっているとどうやらリダイレクトが悪さをしているようです。
たとえばログイン処理でログインに成功するとログイン後のトップページへリダイレクトするわけですが、そうすると正常にセッションが更新されません。
リダイレクトをやめて一度ページを表示するなど出力をクローズしておけば期待した動きをしてくれます。

でも、CGI::redirectとCGI::Sessionの相性が悪いという話は聞いたことがありません。自分の開発環境では一度もそういう現象には出くわしたことがありません。
環境が違う点といえば・・・cgiwarpぐらいかな。「CGI::Session coreserver」とかでぐぐっても同じ現象の記事が見つからないので自分の書き方が悪いのかな~

CentOS5.4でCPANを更新すると警告が大量に出た

えらいことになった。
とりあえずTerm::ReadKeyを入れればいいらしい

[root@localhost ~]# cpan
Sorry, we have to rerun the configuration dialog for CPAN.pm due to
some missing parameters...

Normally CPAN.pm keeps config variables in memory and changes need to
be saved in a separate 'o conf commit' command to make them permanent
between sessions. If you set the 'auto_commit' option to true, changes
to a config variable are always automatically committed to disk.

 
Always commit changes to config variables to disk? [no] 

A Build.PL is run by perl in a separate process. Likewise we run
'./Build' and './Build install' in separate processes. If you have any
parameters you want to pass to the calls, please specify them here.

Typical frequently used settings:

    --install_base /home/xxx             # different installation directory

 
Parameters for the 'perl Build.PL' command? [] 

Parameters for the './Build' command? Setting might be:

    --extra_linker_flags -L/usr/foo/lib  # non-standard library location

 
Your choice: [] 

Do you want to use a different command for './Build install'? Sudo
users will probably prefer:

    su root -c ./Build
 or
    sudo ./Build
 or
    /path1/to/sudo -u admin_account ./Build

 
or some such. Your choice: [./Build] 

Parameters for the './Build install' command? Typical frequently used
setting:

    --uninst 1                           # uninstall conflicting files

 
Your choice: [] 



Please remember to call 'o conf commit' to make the config permanent!

Constant subroutine __USE_POSIX undefined at /usr/lib/perl5/5.8.8/i386-linux-thread-multi/features.ph line 8,  line 5.
Constant subroutine __USE_POSIX2 undefined at /usr/lib/perl5/5.8.8/i386-linux-thread-multi/features.ph line 9,  line 5.
Constant subroutine __USE_POSIX199309 undefined at /usr/lib/perl5/5.8.8/i386-linux-thread-multi/features.ph line 10,  line 5.
Constant subroutine __USE_POSIX199506 undefined at /usr/lib/perl5/5.8.8/i386-linux-thread-multi/features.ph line 11,  line 5.
Constant subroutine __USE_XOPEN undefined at /usr/lib/perl5/5.8.8/i386-linux-thread-multi/features.ph line 12,  line 5.
Constant subroutine __USE_XOPEN_EXTENDED undefined at /usr/lib/perl5/5.8.8/i386-linux-thread-multi/features.ph line 13,  line 5.
Constant subroutine __USE_UNIX98 undefined at /usr/lib/perl5/5.8.8/i386-linux-thread-multi/features.ph line 14,  line 5.
Constant subroutine __USE_LARGEFILE undefined at /usr/lib/perl5/5.8.8/i386-linux-thread-multi/features.ph line 16,  line 5.
Constant subroutine __USE_LARGEFILE64 undefined at /usr/lib/perl5/5.8.8/i386-linux-thread-multi/features.ph line 17,  line 5.
Constant subroutine __USE_FILE_OFFSET64 undefined at /usr/lib/perl5/5.8.8/i386-linux-thread-multi/features.ph line 18,  line 5.
Constant subroutine __USE_BSD undefined at /usr/lib/perl5/5.8.8/i386-linux-thread-multi/features.ph line 19,  line 5.
Constant subroutine __USE_SVID undefined at /usr/lib/perl5/5.8.8/i386-linux-thread-multi/features.ph line 20,  line 5.
Constant subroutine __USE_MISC undefined at /usr/lib/perl5/5.8.8/i386-linux-thread-multi/features.ph line 21,  line 5.
Constant subroutine __USE_GNU undefined at /usr/lib/perl5/5.8.8/i386-linux-thread-multi/features.ph line 23,  line 5.
Constant subroutine __USE_REENTRANT undefined at /usr/lib/perl5/5.8.8/i386-linux-thread-multi/features.ph line 24,  line 5.
Constant subroutine _POSIX_SOURCE undefined at /usr/lib/perl5/5.8.8/i386-linux-thread-multi/features.ph line 49,  line 5.
Constant subroutine _POSIX_C_SOURCE undefined at /usr/lib/perl5/5.8.8/i386-linux-thread-multi/features.ph line 51,  line 5.
Constant subroutine _XOPEN_SOURCE undefined at /usr/lib/perl5/5.8.8/i386-linux-thread-multi/features.ph line 53,  line 5.
Constant subroutine _XOPEN_SOURCE_EXTENDED undefined at /usr/lib/perl5/5.8.8/i386-linux-thread-multi/features.ph line 55,  line 5.
Constant subroutine _LARGEFILE64_SOURCE undefined at /usr/lib/perl5/5.8.8/i386-linux-thread-multi/features.ph line 57,  line 5.
Constant subroutine _LARGEFILE_SOURCE undefined at /usr/lib/perl5/5.8.8/i386-linux-thread-multi/features.ph line 104,  line 5.
Constant subroutine __USE_ISOC99 undefined at /usr/lib/perl5/5.8.8/i386-linux-thread-multi/features.ph line 108,  line 5.
Constant subroutine __GNU_LIBRARY__ undefined at /usr/lib/perl5/5.8.8/i386-linux-thread-multi/features.ph line 156,  line 5.

cpan shell -- CPAN exploration and modules installation (v1.9402)
Enter 'h' for help.

                                                                                Can't ioctl TIOCGETP: 無効な引数です
Consider installing Term::ReadKey from CPAN site nearby
        at http://www.perl.com/CPAN
Or use
        perl -MCPAN -e shell
to reach CPAN. Falling back to 'stty'.
        If you do not want to see this warning, set PERL_READLINE_NOWARN
in your environment.


どうやらTerm::ReadKeyというものが必要なようなので、いれてみる。

cpan[1]> install Term::ReadKey
CPAN: Storable loaded ok (v2.15)
Going to read '/root/.cpan/Metadata'
  Database was generated on Tue, 15 Dec 2009 08:56:54 GMT
Running install for module 'Term::ReadKey'
Running make for J/JS/JSTOWE/TermReadKey-2.30.tar.gz

  CPAN: checksum security checks disabled because Digest::SHA not installed.
  Please consider installing the Digest::SHA module.

CPAN: Time::HiRes loaded ok (v1.9717)
Scanning cache /root/.cpan/build for sizes
............................................................................DONE
CPAN: Compress::Zlib loaded ok (v1.42)
CPAN: Archive::Tar loaded ok (v1.54)
TermReadKey-2.30/
TermReadKey-2.30/genchars.pl
TermReadKey-2.30/Makefile.PL
TermReadKey-2.30/Configure.pm
TermReadKey-2.30/test.pl
TermReadKey-2.30/ReadKey.pm
TermReadKey-2.30/META.yml
TermReadKey-2.30/ReadKey.xs
TermReadKey-2.30/ppport.h
TermReadKey-2.30/MANIFEST
TermReadKey-2.30/README
CPAN: File::Temp loaded ok (v0.22)
CPAN: YAML loaded ok (v0.70)

  CPAN.pm: Going to build J/JS/JSTOWE/TermReadKey-2.30.tar.gz

Checking if your kit is complete...
Looks good
Writing Makefile for Term::ReadKey
cp ReadKey.pm blib/lib/Term/ReadKey.pm
AutoSplitting blib/lib/Term/ReadKey.pm (blib/lib/auto/Term/ReadKey)
/usr/bin/perl -I/usr/lib/perl5/5.8.8 genchars.pl

Writing termio/termios section of cchars.h... Done.
Checking for sgtty...
        Sgtty NOT found.
Writing sgtty section of cchars.h... Done.
/usr/bin/perl /usr/lib/perl5/5.8.8/ExtUtils/xsubpp -noprototypes -typemap /usr/lib/perl5/5.8.8/ExtUtils/typemap  ReadKey.xs > ReadKey.xsc && mv ReadKey.xsc ReadKey.c
gcc -c   -D_REENTRANT -D_GNU_SOURCE -fno-strict-aliasing -pipe -Wdeclaration-after-statement -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/include/gdbm -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m32 -march=i386 -mtune=generic -fasynchronous-unwind-tables   -DVERSION=\"2.30\" -DXS_VERSION=\"2.30\" -fPIC "-I/usr/lib/perl5/5.8.8/i386-linux-thread-multi/CORE"   ReadKey.c
/bin/sh: gcc: command not found
make: *** [ReadKey.o] エラー 127
  JSTOWE/TermReadKey-2.30.tar.gz
  /usr/bin/make -- NOT OK
Running make test
  Can't test without successful make
Running make install
  Make had returned bad status, install seems impossible
Failed during this command:
 JSTOWE/TermReadKey-2.30.tar.gz               : make NO


makeに失敗しました。
しかたがないのでyumからいれてみることに

[root@localhost ~]# yum install perl-Term-ReadKey
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
 * addons: rsync.atworks.co.jp
 * base: rsync.atworks.co.jp
 * extras: rsync.atworks.co.jp
 * updates: rsync.atworks.co.jp
Setting up Install Process
No package perl-Term-ReadKey available.
Nothing to do

orz=3
えっと、あとはどうすればいいんだろう?

Net::Amazonをインストールしてみる

Windowの場合、CPANではNOT OKがでるけど、ppmで簡単に追加できた。

Linux(CentOS)の場合、cpanではNOT OKが大量に出て、個別にモジュールを入れていっても、開発系のライブラリがほとんど入ってないためか、それぞれがNOT OKになってしまう。
結局yumから1つづつ入れていくことになった。
perl-XML-DOM
perl-DIgest-SHA
libxml2
libxml2-devel
Sys-Syslog
perl-Log-Log4perl
んだけど、ログに関するライブラリが入らない。
よくよく見ればCPANの起動時にBundle::CPANを入れろと書いてあるではないか。そういうことならと入れてみる。
何事もなく無事に終了し、Net::Amazonも難なく入った。
結局何が問題なのかって、Bundle::CPANを入れてなかったことだけが問題だったのかもしれない。

ActivePerlがモジュールのインストール周りで進化していた

新しいマシンが調達できたので、Windowsを載せかえる作業をしています。
このマシンはクローラとして使うのでサーバやスクリプト等のインストールを行う必要があります。
Perlga使えないとどうしようもないので、真っ先にActivePerlをインストールするわけですが、そういえば5.10になったなと思いながら作業を進めていると、CPANを起動したらMinGWというコンパイラを入れろというメッセージが。
5.8まではこういう表示もなく、手作業でMicrosoftからwin32cのソフトを入れていました。
MinGWというものが何かは良くわかっていませんが、Cのコンパイラであることに違いないでしょう。
そしてCPANでコンパイラが必要なモジュールを入れるときに勝手に探してきてインストールまで行ってくれました。
これはかなり楽になりましたね~

追記)プロンプトからのcpanのインストールコマンドがcpan モジュール名になってますね。
cpan install モジュール名を入れたら怒られました。

PostScript::Simple(PerlでPostScriptのファイルを作成する)

  ただの画像を作成するには、ImageMagickというツールがありますが、
印刷に関係する図形や文字を作成するには、適していません。
ページ記述言語であるPostScriptを利用することが出来れば、印刷にも利用できます。
なお、PostScriptで作成したものをImageMagickに変換するには、
GhostScriptというツールがありますが、日本語等の2バイト文字への扱いが不完全です。
使用したPostScript::Simpleモジュールのバージョンは0.07でした。
CPANには登録されていませんが、Windowsであれば、ppmからインストールできます。

はじめに

PostScriptは、ページ記述言語です。
これを利用することで、様々な図形などを記述することが出来ます。
座標や単位についての解説は、また後述しますが、
基本的に左下を0,0とし、右上に向かうほど大きくなります。
なお、PostScripの画像は、ImageMagickを利用して以下のコマンドでpng画像に変換してあります。
また、画像はトリミングしてありますので、ご注意ください。
一部オプションは文章の説明のみとさせていただいております。

convert sample.ps -trim sample.png

平行移動や回転、拡大縮小の使い勝手はあまりよくないといういか、
まだ未実装のようです。(バージョン0.07現在)
ただ、EPSファイルの埋め込みが出来ますので、その機能が必要で使用しました。
なお、モジュールで使用している変数に直接追加することで、補うことが出来ます。
末尾の改行を忘れると、PostScriptとして記述エラーになることがありますので、
必ず記述しておくようにしましょう。

$ps -> {'pspages'} .= "1.2 1 scale\n";

空のファイルを作成する

何も表示されない空のファイルを作成します。

use PostScript::Simple;
$ps = new PostScript::Simple(papersize => "A4",
                            colour => 1,
                            eps => 0,
                            units => "in");
$ps -> newpage; # ページ宣言
$ps -> output( 'sample.ps' ); # ファイル保存

直線を描く

線を引くには、始点と終点を指定します。
太さと色は、指定しなくても可能です。
引数は左から「始点のx座標」「始点のy座標」「終点のx座標」「終点のy座標」です。
また、色を直接指定することもできますが、継承されるので注意が必要です。
引数は先のものに、「r色の10進表記」「g色の10進表記」「b色の10進表記」を加えます。

use PostScript::Simple;
$ps = new PostScript::Simple(papersize => "A4",
                            colour => 1,
                            eps => 0,
                            units => "in");
$ps -> newpage; # ページ宣言
$ps -> setlinewidth( 0.01 );   # 線の太さを指定
$ps -> setcolour( 255, 0, 0 ); # 線の色を指定
$ps -> line( 1, 1,  3, 3 );             # 直線を描く
$ps -> line( 2, 1,  1, 2,  0, 0, 255 ); # 色を指定して直線を描く
$ps -> output( 'sample.ps' ); # ファイル保存

このようになります。

直線画像
png画像、146×146ピクセル

折れ線を描く

折れ線を描くには、2通りの方法が用意されています。

一本ずつ個別に指定する

直線を引いた後に次の座標を指定します。
lineメソッドを利用しないままlinextendメソッドを呼び出すと、警告が表示されます。
太さと色は、指定しなくても可能です。
引数は継続して線を描く、「次のx座標」「次のy座標」です。

use PostScript::Simple;
$ps = new PostScript::Simple(papersize => "A4",
                            colour => 1,
                            eps => 0,
                            units => "in");
$ps -> newpage; # ページ宣言
$ps -> setlinewidth( 0.01 );   # 線の太さを指定
$ps -> setcolour( 255, 0, 0 ); # 線の色を指定
$ps -> line( 1, 1,  3, 3 ); # 直線を描く
# 続きの線を描く
$ps -> linextend( 2, 3 );
$ps -> linextend( 3, 2 );
$ps -> output( 'sample.ps' ); # ファイル保存

このようになります。

折れ線画像
png画像、146×146ピクセル

一度に指定する

折れ線を描くには、直線を引いた後に次の座標を指定します。
lineメソッドを利用しないままlinextendメソッドを呼び出すと、警告が表示されます。
太さと色は、指定しなくても可能です。
引数は、「始点のx座標」「始点のy座標」「終点のx座標」「終点のy座標」です。
平行移動させるには、「offset => [ (x座標), (y座標) ]」オプション、
塗り潰すには「filled => 1」オプション、
回転させるには、「rotate => (角度)」オプションもあります。

use PostScript::Simple;
$ps = new PostScript::Simple(papersize => "A4",
                            colour => 1,
                            eps => 0,
                            units => "in");
$ps -> newpage; # ページ宣言
$ps -> setlinewidth( 0.01 );   # 線の太さを指定
$ps -> setcolour( 255, 0, 0 ); # 線の色を指定
$ps -> polygon( 1, 1,  2, 3,  3, 2, 2, 1, 1, 3 ); # 折れ線を描く
$ps -> output( 'sample.ps' ); # ファイル保存

このようになります。

折れ線画像
png画像、146×146ピクセル

四角形を描く

線を描くのと同じように、四角形を構成する始点と終点を指定します。
太さと色は、指定しなくても可能です。
引数は、「始点のx座標」「始点のy座標」「終点のx座標」「終点のy座標」です。
塗り潰すには「filled => 1」オプションがあります。

use PostScript::Simple;
$ps = new PostScript::Simple(papersize => "A4",
                            colour => 1,
                            eps => 0,
                            units => "in");
$ps -> newpage; # ページ宣言
$ps -> setlinewidth( 0.01 );   # 線の太さを指定
$ps -> setcolour( 255, 0, 0 ); # 線の色を指定
$ps -> box( 1, 1,  3, 3 );     # 四角形を描く
$ps -> output( 'sample.ps' ); # ファイル保存

このようになります。

四角形画像
png画像、146×146ピクセル

円を描く

円を描くには、中心と半径を指定します。
太さと色は、指定しなくても可能です。
引数は、「中心のx座標」「中心のy座標」「半径の長さ」です。

use PostScript::Simple;
$ps = new PostScript::Simple(papersize => "A4",
                            colour => 1,
                            eps => 0,
                            units => "in");
$ps -> newpage; # ページ宣言
$ps -> setlinewidth( 0.01 );   # 線の太さを指定
$ps -> setcolour( 255, 0, 0 ); # 線の色を指定
$ps -> circle( 2, 2,  1 );     # 円を描く
$ps -> output( 'sample.ps' ); # ファイル保存

このようになります。

円画像
png画像、146×146ピクセル

孤を描く

孤を描くには、中心と半径、そして開始角と終了角を指定します。
太さと色は、指定しなくても可能です。
引数は、「中心のx座標」「中心のy座標」「半径の長さ」「開始角度」「終了角度」です。
角度は右が始点、つまり座標では「(中心のx座標) + (半径の長さ), 中心のy座標」になります。
塗り潰すには「filled => 1」というオプションがありますが、
あらかじめ孤を描いておかないと利用できないなど、使い勝手がよろしくありません。

use PostScript::Simple;
$ps = new PostScript::Simple(papersize => "A4",
                            colour => 1,
                            eps => 0,
                            units => "in");
$ps -> newpage; # ページ宣言
$ps -> setlinewidth( 0.01 );     # 線の太さを指定
$ps -> setcolour( 255, 0, 0 );   # 線の色を指定
$ps -> arc( 2, 2, 1,  0,  270 ); # 孤を描く
$ps -> output( 'sample.ps' ); # ファイル保存

このようになります。

孤画像
png画像、146×146ピクセル

文字を描く

文字を書くには、フォントの指定が必要になります。
日本語を扱う場合には、特にフォントに関する知識が必要となります。
画像に変換する場合には、GhostScriptの設定が必要です。
インストールしたままの状態では、フォントが見つからないという警告が表示され、
画像に変換できませんので、注意してください。
設定の方法については、別に機会にいたします。
フォントの太さを指定するメソッドが別にありますので、線の太さを指定するメソッドは必要ありません。
配置を指定する「align => (left/center/right)」オプションと、
回転を指定する「rotate => (角度)」オプションがあります。

use PostScript::Simple;
$ps = new PostScript::Simple(papersize => "A4",
                            colour => 1,
                            eps => 0,
                            units => "in");
$ps -> newpage; # ページ宣言
$ps -> setcolour( 255, 0, 0 );   # 線の色を指定
$ps -> setfont( 'MS-Mincho-90ms-RKSJ-H', 36 ); # フォントをエンコード方法なども含めて指定
$ps -> text( 1, 1, 'ぺんラボ' );               # 文字はShift_JISで指定
$ps -> output( 'sample.ps' ); # ファイル保存

このようになります。

文字画像
png画像、140×32ピクセル

解説していないメソッドについて

以下のメソッドについては、
モジュールの使い方というよりもPostScriptの解説になりますので、
このページではただいま解説は行っておりません。
詳しくは、PostScriptの解説を行っているサイトや、PostScript::Simpleモジュールをご覧下さい。

  • newpage
  • putput
  • get
  • geteps
  • circletext
  • curve
  • curveextend
  • newpath
  • moveto
  • importepsfile
  • importeps

更新履歴

2008-06-22
一部のメソッドについて解説を追加
2008-06-15
公開