* mod_perl時の注意点 [#ge012083]
#setlinebreak(on);

以下は 「[[Apacheをmod_perl対応にする]]」 で設定した環境下で確認できた事象です。

 ◆カレントディレクトリがルート( / )になる。

  確認用CGI : /path/to/cgi-bin/directory.cgi
#html(<div style="border:1px solid #000000;background:white;padding:4px;margin-left:30px;">)
&#35;!/usr/bin/perl
&nbsp;
print "Content-type: text/plain\n\n";
print "カレントディレクトリ : " . `pwd` . "\n";
exit(0);
#html(</div>)

   Apacheの実行ディレクトリになるとの情報も有ったが、自宅サーバでは / になっていた。
   なのでモジュール検索PATH @INC 等を変更する時は、注意が必要だな。と思っていたら
   そもそも モジュール検索PATH をイジル事ができないらしい。※次を参照。

 ◆%%unshift、push で変更を加えた @INC(モジュール検索PATH)が使用されない。%%
  → [[http://mt.endeworks.jp/d-6/2010/02/incuse.html:http://mt.endeworks.jp/d-6/2010/02/incuse.html]] によると認識が違うそうです。
    が、誤りから学んだ事を残しておくという意味で''以下のメモはそのまま残すが信じちゃダメ'!'
    上記URLでは「認識が違う」と柔らかめの指摘を頂いてるが、そもそもperlの勉強不足だった。。ハズかしぃ〜!
    詳しくは [[perlモジュールの検索PATHについて]] を参照。

  確認用CGI : /path/to/cgi-bin/lib_search.cgi
#html(<div style="border:1px solid #000000;background:white;padding:4px;margin-left:30px;">)
&#35;!/usr/bin/perl
&nbsp;
(my $owndir = $0) =~ s/^(.+)\/(.+?)\.(.+?)$/$1/;
&nbsp;
use lib qw(./pm);           # これだとカレントがApacheの実行ディレクトリになるので無意味だが。。
unshift @INC, "$owndir/pm"; # こっちでもダメだった。
&nbsp;
use MyClass;
&nbsp;
print "Content-type: text/plain\n\n";
print "MyClassが見つかりました\n";
&nbsp;
my $myclass = new MyClass();
print "MyClassのインスタンスを生成できました\n";
&nbsp;
$myclass->printName();
$myclass = undef;
&nbsp;
exit(0);
#html(</div>)

   上記のcgiから呼び出されるCGI : /path/to/cgi-bin/pm/MyClass.pm
#html(<div style="border:1px solid #000000;background:white;padding:4px;margin-left:30px;">)
&#35;!/usr/bin/perl
&nbsp;
package MyClass;
&nbsp;
sub new{
&nbsp; my $class = shift;
&nbsp; bless { name => "MyClass",} , $class;
}
&nbsp;
sub printName {
&nbsp; my $self = shift;
&nbsp; print $self->{name} . "のprintNameを実行しました\n";
}
1;
#html(</div>)

  上記のcgiにアクセスすると

    http&#58;//example.com/cgi-bin/lib_search.cgi         ...OK

    http&#58;//example.com/cgi-perl-run/lib_search.cgi    ...Internal Server Error が発生

  【エラーログ】
#html(<table style="margin-left:30px;"><tr><td style="background:#000000;color:white;width:700px;">)
Can't locate MyClass.pm in @INC (@INC contains: ./pm /usr/lib/perl5/5.8.0/i386-linux-thread-multi
/usr/lib/perl5/5.8.0 /usr/lib/perl5/site_perl/5.8.0/i386-linux-thread-multi
/usr/lib/perl5/site_perl/5.8.0 /usr/lib/perl5/site_perl /usr/lib/perl5/vendor_perl/5.8.0/i386-linux-thread-multi
/usr/lib/perl5/vendor_perl/5.8.0 /usr/lib/perl5/vendor_perl . /usr/local/apache2) 
at /home/system/htdocs/web/mod_perl/lib_search.cgi line 8.
BEGIN failed--compilation aborted at /path/to/cgi-bin/lib_search.cgi line 8.
#html(</td></tr></table>)

  unshift で追加した @INC が反映されていない。
  但し、use は効いている模様。
  ※useでフルPATH指定すれば問題なさげ。
     ↓
  eval("use lib '$owndir/pm'");  でOK。

 ◆起動されるスクリプトのグローバル変数は使いまわされる(Registry)

  確認用CGI : /path/to/cgi-bin/global_var.cgi
#html(<div style="border:1px solid #000000;background:white;padding:4px;margin-left:30px;">)
&#35;!/usr/bin/perl
&nbsp;
print "Content-Type: text/plain\n\n";
&nbsp;
my $cnt = 0;
&nbsp;
for (1..5) {
&nbsp;   increment($cnt);
}
sub increment {
&nbsp;   $cnt++;
&nbsp;   print "Count is $cnt\n";
}
&nbsp;
exit(0);
#html(</div>)

  http&#58;//example.com/cgi-bin/global_var.cgi(通常版)への2回目のアクセス時
#html(<div style="border:1px solid #000000;background:white;padding:4px;margin-left:30px;">)
Count is 1
Count is 2
Count is 3
Count is 4
Count is 5
#html(</div>)

  http&#58;//example.com/cgi-perl-run/global_var.cgi(PerlRun版)への2回目のアクセス時
#html(<div style="border:1px solid #000000;background:white;padding:4px;margin-left:30px;">)
Count is 1
Count is 2
Count is 3
Count is 4
Count is 5
#html(</div>)

  http&#58;//example.com/cgi-registry/global_var.cgi(Registry)への2回目のアクセス時
#html(<div style="border:1px solid #000000;background:white;padding:4px;margin-left:30px;">)
Count is 6
Count is 7
Count is 8
Count is 9
Count is 10
#html(</div>)

  以下のように global変数を使用せず、名前空間をしっかり管理すればOK。
#html(<div style="border:1px solid #000000;background:white;padding:4px;margin-left:30px;">)
&#35;!/usr/bin/perl
&nbsp;
print "Content-Type: text/plain\n\n";
&nbsp;
my $cnt = 0;
&nbsp;
for (1..5) {
&nbsp;   $cnt = increment($cnt);
}
sub increment {
&nbsp;   my $cnt = $_[0];
&nbsp;   $cnt++;
&nbsp;   print "Count is $cnt\n";
&nbsp;   return $cnt;
}
&nbsp;
exit(0);
#html(</div>)

 ◆キャッシュされたスクリプトのmain処理(?)は実行されない (Registry、PerlRunも?)

  確認用CGI : /path/to/cgi-bin/use_require.cgi
#html(<div style="border:1px solid #000000;background:white;padding:4px;margin-left:30px;">)
&#35;!/usr/bin/perl
&nbsp;
print "Content-Type: text/plain\n\n";
&nbsp;
(my $owndir = $0) =~ s/^(.+)\/(.+?)\.(.+?)$/$1/;
require "$owndir/pm/sub_module.pl";
&nbsp;
subModule::argPrint(time);
&nbsp;
while (my ($key,$val) = each(%INC)) {
&nbsp;   print "$key=$val\n";
}
exit(0);
#html(</div>)

  requireされるCGI : /path/to/cgi-bin/pm/sub_module.cgi
#html(<div style="border:1px solid #000000;background:white;padding:4px;margin-left:30px;">)
&#58;!/usr/bin/perl
&nbsp;
package subModule;
&nbsp;
argPrint("モジュール自身のファイルからの呼び出し");
&nbsp;
sub argPrint {
&nbsp;   print "受け取った引数は(". $_[0] .")ですか?\n";
}
1;
#html(</div>)

   とした時 Registry版だと、起動されるスクリプトから明示的に呼び出されていない処理は実行されない。
   ※「受け取った引数は("モジュール自身のファイルからの呼び出し")ですか?」は表示(実行)されない。
    ( PerlRun はなぜか実行されたり、されなかったりする。。)

   起動されるスクリプトから明示的に、メソッドで呼び出されているものは確実に実行される。
   ※「受け取った引数は(1238777288)ですか?」のみ実行される。
   ※ メソッド呼び出しをすると、PerlRun では
    「受け取った引数は("モジュール自身のファイルからの呼び出し")ですか?」も表示される事がある?(良く分からん!)

   基本的に requireされるファイルには main処理(と言っていいのかな?)を記述せず、全てメソッドで実装し、明示的に呼び出す。

 ◆requireされたファイルを変更しても、キャッシュされている為、すぐに反映されない事がある。

  【解決方法】
#html(<div style="border:1px solid #000000;background:white;padding:4px;margin-left:30px;">)
&nbsp;
BEGIN { delete $INC{"/path/to/cgi-bin/sub_module.pl"} };
&nbsp;
#html(</div>)

   を記述して、ロード済みモジュールリストから消してから、再度 require する。



 ◆exit、die を使うとプロセス(子)が落ちる。。らしい
#html(<div style="border:1px solid #000000;background:white;padding:4px;margin-left:30px;">)
&#58;!/usr/bin/perl
&nbsp;



exit;
#html(</div>)

   とするとApacheのプロセスが落ちるとの情報があったが、実験してみても落ちなかった。

#html(<div style="border:1px solid #000000;background:white;padding:4px;margin-left:30px;">)
&nbsp;
exit(0);
&nbsp;
#html(</div>)

   だと問題ないようなので exit は全てこの記述に統一する。


トップ   一覧 単語検索 最終更新   ヘルプ   最終更新のRSS