View Full Version : どんなperlでもモジュールの方がいいの?
usopion
2001/11/26, 09:42 PM
ちょっと負荷が季になっているので、
CGIをmod_perlで動かしてみたいと思っているのですが、
利用の際に注意すべき点はなんでしょうか。
たとえば、CGIで利用する画像ファイルなどを
shared_htmlにおいてもちゃんと呼び出しはできるのでしょうか。
スクリプトは基本時にはそのままで動作するようですが、
特に修正すべきことはありますか?
また、モジュール版にすることでむしろ
負荷が増大するようなことはあるのでしょうか?
そのほか、セキュリティ面などで普通ののperlで動かすよりも
問題になることなどはないですか?
mod_perlにするだけで、なんのリスクもなく負荷が減るのなら、
初めからCGIをmod_perlで動作するように設定しておけばいいと思うのですが、
それをしていないと言うことは、何らかのリスクがあると思うのですが
どうなのでしょう?
これは利用者側と言うよりむしろ、サーバ側のリスクなのでしょうか?
たとえば、エラーの発生時に、普通のperlより落ちやすくなるとか?:confused:
yoshio
2001/11/27, 02:44 AM
こんにちは、usopionさん。
スクリプトは基本時にはそのままで動作するようですが、
特に修正すべきことはありますか?
取り敢えず「相対パス指定で外部ファイルを呼び出している&そのファイルがshared_html下に存在しない(public_html下にある)」場合は、絶対パス指定で呼び出すように変更する必要がありますね。
あと画像は、確認したところ特に問題は無いみたいです。
また、モジュール版にすることでむしろ
負荷が増大するようなことはあるのでしょうか?
これは無いんじゃないでしょうか?逆に負荷が増大するなら、わざわざモジュール動作を推奨しないと思います。
そのほか、セキュリティ面などで普通のperlで動かすよりも
問題になることなどはないですか?
私も気になります。「CGIをモジュールで動作させようかな?」と思っていたところ、仕様 (http://www.xrea.com/jp/spec.shtm)の中で
※shared_html内のASP/JSP/PHP/mod_perlの実行権はサーバー側となり、悪意のあるユーザはソース、データを閲覧・改竄できる場合があります。
という一文を発見してしまったもので…いまいちモジュール化を実行できずにいます。
通常のpublic_html下での動作と比べて、どの程度の危険があるのかが知りたいところです。
cucu81
2001/11/27, 10:48 AM
セキュリティーを維持するためには、
「自分で」プログラムを変える必要があります。
mod_perl、mod_ruby その他、mod_言語名 シリーズは
なんではやいのでしょうか?
プログラム本体部分の実行速度が速くなるわけではありません。
(そんなことあったら不思議ですね…)
例えばPerl言語の場合、「perl」というインタプリタプログラムを起動しますね。
この起動時間が実は一番問題なのです。
チャットなどがやたらに負荷率が高いのは、「有効でもなんでもない、
このperlインタプリタをわざわざCPUを割いて「起動」して、2行ほどメッセージ
書いて終わり、インタプリタ終了」
という「しょぼいことに対して、時間のかかるインタプリタ起動動作、
が頻発して起きるために」負荷率が高いわけです。
(ようするに、「起動と終了」が大部分を占めてしまい、
スクリプト内容の処理時間はほとんど
なくてとてももったいない使い方なわけです)
mod_perl はここを改善しています。
mod_perl は簡単な話、ApacheがPerlインタプリタの役目も果たせるようにするものです。
Apache はずっと起動したままですので、「起動と終了」のもったいない時間
が発生しません。
このため「モジュールを使用すれば速い」という関係式が成立し、
メリットがあるわけです。
では、そのデメリットもみていきましょう。
mod_perl とはPerlプログラムのメイン関数のようなものです。
今回はあえてわかりやすいように、Perlプログラムに置き換えてみましょう。
===============================
sub main {
}
===============================
みなさんがmod_perlを使った場合、そのプログラムは適当な名前を
割り振られ、サブルーチン化され、mainから呼び出されるようになります。
===============================
sub main {
&A_module() # Aさんのモジュール
&B_module() # Bさんのモジュール
&CuCu81_chu_module() # CuCu81の厨なモジュール
}
===============================
さてさて、ここで、Perlはスカラー変数(例:$abcd)などをいっぱい
使用しますが、確か「my」をつけない場合、
『サブルーチンA_module』の中で、生成したスカラー変数を
『サブルーチンCuCu81_chu_module』でも使えるのでしたね。
ようするにPerlでは『デフォルトでは全てグローバル変数』です。
ということは、お互いがお互いの変数を覗きたい放題になると言うことです。
また、サブルーチンA_moduleが終了しても、それはただのサブルーチン
ですから、プログラム(main) は終了しません。
自分のプログラムが終了してもグローバル変数が残っていることがわかります。
もう危険性はおわかりでしょう。 そういうことでmod_perlの方が軽くなる
とはわかっていても、早々容易に使用できないというわけです。
基本的には、全ての変数をローカル変数化して対応してください。
いじょ
P.S.
shared_html 内に置くソースには平分パスワードは入れないことです。
暗号関数の結果の方をソース中には書いておき、それと比較するように
しましょう。
yoshio
2001/11/27, 12:33 PM
cucu81さん、解りやすい説明、ありがとうございます。
実は今の今まで、「mod_perlってなんで負荷が低いんやろか?」等と思ってたもので…。
さて、セキュリティの話に戻りますと、cucu81さんの説明で、
全ての変数がグローバル変数に変化し、他ユーザが別のスクリプト内でそれを利用できる=悪意を持ったユーザが適当な変数($passや$log)を記録し、悪用することが出来る→全ての変数をローカル変数化し、これを阻止する必要がある
という図式が頭の中で出来上がりました。
しかしスクリプト内の変数を全てローカル変数化するとは言っても、「高機能CGI」として配布されているスクリプトは大半が長大(しかも複数のファイルに分散されている)で、全ての変数をローカル変数化するのは難しいと思います。そこで「覗かれては(改変されては)マズイ変数(具体的には、大概のスクリプトの前半にある『設定項目』と呼ばれているような部分です)のみをローカル変数化したら楽だろうな」と思ったのですが、いかがでしょうか?
usopion
2001/11/27, 04:24 PM
なるほど、
どこかで、全ての変数を明示的に宣言する必要があると
読んだ気がしていたのですが、
そういう危険性もあるのですね。
基本的には、全ての変数をローカル変数化して対応してください
つまり、my();宣言してあげればいいのだと思いますが、
その有効範囲に季を付ける必要がありますよね、
とくに、外部ファイルなどをrequireで呼び出す場合には
けっこうややこしいことになりそうです・・・
例
#!c:/Perl/bin/perl
#実行スクリプト=test.cgi
$a="main";
my($b)="main";
my($c)="main";
my($d)="main";
print "Content-type: text/html; charset=Shift_JIS\n\n";
require "initial.ini";
print "a=$a<BR>\n";
print "b=$b<BR>\n";
print "c=$c<BR>\n";
print "d=$d<BR>\n";
print "e=$e<BR>\n";
print "f=$f<BR>\n";
&riqsub;
&mainsub;
exit;
sub mainsub{
print "<BR>mainsub<BR>\n";
print "a=$a<BR>\n";
print "b=$b<BR>\n";
print "c=$c<BR>\n";
print "d=$d<BR>\n";
print "e=$e<BR>\n";
print "f=$f<BR>\n";
}
--------------------------
#設定ファイル=initial.ini
$c="riqu";
my($d)="riqu";
$e="riqu";
my($f)="riqu";
sub riqsub{
print "<BR>riqsub<BR>\n";
print "a=$a<BR>\n";
print "b=$b<BR>\n";
print "c=$c<BR>\n";
print "d=$d<BR>\n";
print "e=$e<BR>\n";
print "f=$f<BR>\n";
}
1;
上のコードを実行すると、
a=main
b=main
c=main
d=main
e=riqu
f=
riqsub
a=main
b=
c=riqu
d=riqu
e=riqu
f=riqu
mainsub
a=main
b=main
c=main
d=main
e=riqu
f=
このようになります。
my();宣言したファイルは、そのファイル内でのみ有効と言うことですよね。
となると、riquireで設定ファイルを呼び出すような場合は、
グローバル変数にならざるを得ないと言うことですよね・・・
これをうまいことやる方法はないのでしょうかね。 :(
あと、my();宣言しない配列変数に、
push関数などで、要素を追加していくコードがあった場合、
値がクリアされないために、スクリプトを呼び出すたびに
配列の要素が増えていき、メモリがパンク・・・
なんて事態も発生しうるのでしょうか?:D
dutch
2001/11/27, 04:42 PM
通常のperlをモジュール版に変えるときに、
サブルーチンをrequireコマンドで読み込むと、負荷がかかるのでしょうか?
例:上のプログラムを次のように変更してみる。
#!c:/Perl/bin/perl
#実行スクリプト=test.cgi
$a="main";
my($b)="main";
my($c)="main";
my($d)="main";
print "Content-type: text/html; charset=Shift_JIS\n\n";
require "initial.ini";
print "a=$a<BR>\n";
print "b=$b<BR>\n";
print "c=$c<BR>\n";
print "d=$d<BR>\n";
print "e=$e<BR>\n";
print "f=$f<BR>\n";
require 'riqsub.pl'; #&riqsub; から変更
require 'mainsub.pl'; #&mainsub; から変更
exit;
--------------------------
#設定ファイル=initial.ini
$c="riqu";
my($d)="riqu";
$e="riqu";
my($f)="riqu";
1;
--------
#mainsub.pl
print "<BR>mainsub<BR>\n";
print "a=$a<BR>\n";
print "b=$b<BR>\n";
print "c=$c<BR>\n";
print "d=$d<BR>\n";
print "e=$e<BR>\n";
print "f=$f<BR>\n";
1;
-------
#riqsub.pl
print "<BR>riqsub<BR>\n";
print "a=$a<BR>\n";
print "b=$b<BR>\n";
print "c=$c<BR>\n";
print "d=$d<BR>\n";
print "e=$e<BR>\n";
print "f=$f<BR>\n";
1;
usopion
2001/11/27, 06:20 PM
すいません。
訂正します。
my();宣言ではなく、local();宣言すべきですね。
スクリプトの先頭で、利用する変数を
全て
local();
で宣言すれば、そのスクリプト内および、
requireで呼び出されたファイル名でのみ、
グローバル変数かのように振る舞い、
スクリプトの呼び出しが終わると変数はクリアされる
と考えていいのかな?
local($a)="value";
local($b);
require 'test.pl';
---略---
exit;
-----
test.pl
$b="value";
vBulletin® v3.6.8, Copyright ©2000-2008, Jelsoft Enterprises Ltd.