今日からCGIプログラマー
《第1回》CGIを動作させてみる
この自作道。デバッグはコマンド・プロンプト風味で

 
CGIなんて要らない
 ……って考えてる人発見。
 本当にそうだろうか。CGI入門というと、たいていの書籍は、FTPのアップロー
ドやパーミッションの設定から始まり、「UNIXサーバ」だとか、「CGIの置ける
プロパイダの確認」だとかいう文字が踊る。

 コチコチ頭は誰だ?

■旧い考え
●CGIは、プロバイダや研究室などのサーバの中に置き、公開コンテンツを作る。
●Perl?実行速度遅いんでしょ?やっぱCだよ。
●Perlはリソース喰うしね。

■新しい考え
●常時回線だもん。CGIは自宅のWindowsマシンで動かそう。
●自分専用か、仲間専用(だから、動けばいい……バキ)。
●実行速度もリソースも気になんない。だってマシン速いし。
●携帯とか、どこかのPCから、自分のデータに快適アクセス。
●もっと小規模に、LANの中や、ローカルから見れれば充分。

 つまり、「公開コンテンツ」とかを考えてしまうから、「CGI、これすなわち、ア
クセス・カウンタ」とか「掲示板」とかそういう発想になるワケ。
 そうじゃなくて、自分のためのプログラムを、気軽に便利に作れるのがPerl+C
GI。もっと楽しいもんなのよ……。

 さらに、Perlは、限りなくインタープリタに近いコンパイル言語だから、パスを
変えたりするだけで、平気でUnix上でも動いたりする。こりゃ、便利。

 もちろん、最初はフリーウェアをgetしたほうが話が早いだろう。だが、スクリプ
トって、作れば作るだけ開発は速くなるし、フリーウェアでは、どうにも痒いところに
手が届かない場合にだけ、Perl+cgiで補うって形でも、めちゃ便利。
 他人のために提供するプログラムじゃないからお気楽なもんよ。それでも、不便なフ
リーウェアだけを、使って生きてくんですか?

 え?ひょっとしてPerlをまったく知らない?いや、ぜんぜんOK。だって、たと
えば、「とほほのPerl入門」(http://tohoho.wakusei.n
e.jp/wwwperl.htm)なんかで、本連載のスクリプトが何をしているか
追っかければ、すぐに使えるようになるから。


入手・設定
 誌面の都合で省略するが、「jperl」「入手」でand検索をかければ、よいペ
ージがいくらでも検索できる。
 最初からjperlで供給されているタイプではなく、「ActivePerl 5
.XX」をインストール後、「日本語パッチ」を当てる、というスタイルでインストー
ルするタイプの方法を選ぶのがコツ。

 「C:\Perl\bin\MSWin32-x86-object\jperl.
exe」というパスに、jperlがインストールされるのが、正式なパッケージ。実
際には、jperlよりもperlを使うことが多いのだが、ときどきjperlも便
利なので、両方欲しいところ。

 で、CGIっていうのは、要するに、ブラウザ越しに動くプログラムって思えばいい
。だから、Perlだけじゃダメで、「ブラウザでアクセスしたときに応答するプログ
ラム」=「Webサーバ」ってやつもインストールする必要がある。

 これは、Apache(http://japache.infoscience.
co.jp/index.html)と、AN HTTP Server(http:
//www.st.rim.or.jp/~nakata/index.html)を
、両方、インストールしよう。どちらか片方だけにしたかったら、やはりApache
だろう。

 Apacheは、素直に、デフォルトの「C:\Program Files\Ap
ache Group」以下にインストールしてほしい。設定の要点を書く。

@「httpd.default.conf」を「httpd.conf」にリネーム

A以下、http.confを書き換える。
 「DocumentRoot "C:/Program Files/Apache
 Group/Apache/htdocs"」を、たとえば、「DocumentR
oot "C:/html"」のようにHTMLを置きたいディレクトリに書き換える
。
BAにともない、「<Directory "C:/Program File
s/Apache Group/Apache/htdocs">」を「<
;Directory "C:/html">」に書き換える。
C同じように、「ScriptAlias……」の行も、「ScriptAlias 
/cgi-bin/ "C:/perl/cgi"」のように書き換え、ディレクトリ
もこの場所に作る。
Dまた、忘れずに、「<Directory "C:/Program Fil
es/Apache Group/Apache/cgi-bin">」を「&
lt;Directory "C:/perl/cgi/">」に書き換えよう
。
Eこのフォルダ(c:\perl\cgi)に、「jcode.pl」を、必ず、入れ
ておく。

 起動と終了は、「スタート」からたどり、「ControlApacheServe
r」から、startやstopが選択できる。startしても、何も起こらない?
だーいじょうぶ。次の章に進もう。


<Apacheの起動>

 AN HTTPDのほうも、設定の要点だけ書く。

@「ポート80」→「81」
A常駐アイコンを右クリック→「オプション・一般」→「一般」タブで開く設定ウィン
ドの「拡張子  実行プログラム  etc」の表から、「pl,cgi」を選択→「
編集」→「#!の行を調べる」にチェック。(これ絶対!)
B「エイリアス」タブ→「仮想パス」欄の、「cgi-bin」は、Apacheで設
定したパスと同じにする。


<設定の様子>

 @により、Apacheと完全に共存できる。Aにより、jperlとperlを使
い分けられる。

 起動と終了は、一般のWindows常駐ソフトと同じ感覚である。


動作確認
 cgiの動作確認には、決まって、「hello」の文字を表示させることになって
いる。だが、本当に、helloが見たいか?私は見たくない。

 リスト1を、「c:\perl\cgi\」に、保存しよう。できれば、EUC+L
Fで保存したほうがいいが、sjis+CRLFでも、きちんと動作した。

 これは、おみくじCGIで、「大吉」が出るまで、自動リロードし続ける。毎朝これ
を起動して、その日を「大吉」にしようという、人生ノウテンキなCGIである(笑)
。
 といっても、必ず「大吉」では毎日占う意味がないので、色とりどりに結果の文字が
変わるなか、最後の「大吉」が赤文字だった場合こそ、ホントの大吉。しかも、一回の
リロードもなく、いきなり赤い大吉に出会った、その日、あなたは、社長になれる!(
と、mikuji.pl様が申しております)。
 ぜひ、ブラウザのホームアドレスをmsnやgoogleから、この「おみくじスク
リプト」に変えよう。

 それにしても、これだけ遊び心のあるスクリプトで、たった14行。これが、Per
l CGIの実力である(びっくりした?)。

 起動方法は、ブラウザのURL欄に、「http://localhost/cgi
-bin/mikuji.pl」と入力すればよい。次々リロードがかかり、「大吉」
が出て止まれば、Apacheのcgiは正常に動作している。
 また、AN HTTPDの動作確認をするには、ブラウザのURL欄に、「http
://localhost:81/cgi-bin/mikuji.pl」と入力すれ
ばよい。このように、Apacheと同じcgiを、AN HTTPDで起動するには
、localhostのあとに、「:81」を追加するのだ。



<mikuji.pl動作中 「:81」がある方は、AN HTTPDでの動作を示
している>

デバッグと運用
 EUCで編集できるテキスト・エディタは必須である。フリーウェアにもよいものが
あるようだ。筆者はシェアウェアの「秀丸エディタ」が手に馴染む。

 さて、入力したがうまく動作しなかった読者はいるだろうか?たった14行のスクリ
プトである。しかし、一発で動作しなかった人も多いはずだ。そこで登場するのが、超
便利なバッチ・ファイル2種類。

p.bat
C:\Perl\bin\perl %1

jp.bat
C:\Perl\bin\MSWin32-x86-object\jperl.ex
e %1

 改行は入れないこと。各1行のシンプルなバッチ・ファイルだ。
 このバッチ・ファイルをバカにしてはならない。よくある「;」の忘れとか、「"」
関連のバグなんかは、ブラウザで起動する前にこのバッチ・ファイルを使うことで、1
00%、駆逐できる。
 さっそくテキスト・エディタで打ち込んで、「c:\perl\cgi」に放り込ん
でおこう。


 さらに準備は続く……。コマンド・プロンプト(またはDOSプロンプト)のショー
トカットを作ろう。これに、「cgi-dir」という名称をつけ、プロパティの「作
業フォルダ」を「c:\perl\cgi」としよう。これで、クリック一発でcgi
ディレクトリに降りられる。

 さっそく、今のショートカットをダブル・クリックして、cgiディレクトリに降り
た状態の、コマンド・プロンプトを起動する。ここで、「p mikuji.pl」と
打ち込んで、Enterすると、写真のように、syntax errorが表示され
る。


<p.batでスクリプトをチェック>

 この場合は、line 9のエラーであるが、9行目がエラーである場合よりも、む
しろ、直前の行で、対応するカッコが閉じていないような場合が多い。「スクリプト修
正」→「p.batのチェック」。プロンプトにHTML文字列が表示されるまで、こ
の作業を繰り返す。

 同じように、jperlスクリプトの場合は、「jp xxx.pl」Enterの
ように使用する。「p.bat」「jp.bat」は、非常に簡単だが、同時に、目か
らウロコの、ほとんど使われていない手法である。


 こんな風に、デバッグはコマンド・プロンプトでやるのが、何しろいっとう速い。

 しかし、パラメータを渡したいときもあるだろう。パラメータは、どうやって渡すの
か?それを解決するのが、リスト2の方法である。

 リスト2を、「c:\perl\cgi\」に、保存しよう。EUC+LFで保存す
ること。

 ブラウザから、「http://localhost/cgi-bin/test.
pl?p1=2&p2=6」を表示させると、p1とp2というパラメータがcgiに
渡る。


<ブラウザ越しにパラメータを渡す>

 同じように、コマンド・プロンプトから、「p test.pl "p1=64&p
2=flog"」を実行したのが、写真である。("記号は必須)。


<プロンプトからパラメータを渡す>

 このように、デバッグしたいスクリプトのパラメータ解釈の前に、「($ARGV[
0]) && (($ENV{'QUERY_STRING'}) || ($ENV
{'QUERY_STRING'} = $ARGV[0]));」と記述しておけば
、コマンド渡しの情報(変数)が存在し、なおかつ、「QUERY_STRING」が
カラだった場合に限って、コマンドから「QUERY_STRING」に情報(変数)
がコピーされる。
 この方法で、大きなcgiを組むようなとき、さまざまな変数をコマンド・プロンプ
トから入力して、デバッグを行なうことができる。

 これも、目からウロコの、簡単なクセになかなか知られていない、とても便利な手法
である。

*
 大急ぎでいろいろ見てきたが、本連載を見れば、Perl+CGIの自作道のとりこ
になることを宣言しておく。そのためにも、perlとWebサーバのインストールに
、ぜひ、挑戦してみてほしい。

HP「今日からCGIプログラマー」(http://www.geocities.
co.jp/SiliconValley-Cupertino/6103/)
(辻豊史)
 
■リスト1 おみくじCGI(mikuji.pl)
#! c:/perl/bin/perl
require "./jcode.pl";srand;$c=(int(rand(5)));$ftr=(int(rand(10)));#占い
@clr = ("#224962","#7794FF","#FF9900","#FF7D7D","#9FE765","#FF4949");
@res=("大凶","凶","末吉","小吉","小吉","中吉","中吉","吉","吉","大吉");
$line = "Content-type: text/html\n\n<!DOCTYPE HTML PUBLIC \"-//W3C//DTD
  HTML 4.0  Transitional//EN\"><HTML><HEAD>
  <META http-equiv=Content-Type content=\"text/html; charset=x-sjis\">
  <TITLE>みくじ</TITLE></HEAD><BODY><FONT size=+4 color=$clr[$c]>
  $res[$ftr] </FONT>";&lprint;# htmlヘッダと結果
if ($ftr <= 8) {$line = "……もう一回!パパンがパンッ!
  <META HTTP-EQUIV=\"refresh\" CONTENT=\"1.5;URL=$ENV{'SCRIPT_NAME'}\">";
  &lprint;} #結果が思わしくない時は、もう一度占う
print "</BODY></HTML>"; #終わり
sub lprint {&jcode'convert(*line,sjis);print $line;} #サブルーチン

■リスト2 パラメータ実験(test.pl)
#! C:\Perl\bin\perl.exe
print "Content-type: text/html\n\n";
#---ブラウザのURL欄で渡すパラメータと、DOS窓のコマンドラインから与える
#---パラメータを揃える、おまじない。二重カッコの位置に注意!
($ARGV[0]) && 
(($ENV{'QUERY_STRING'}) || ($ENV{'QUERY_STRING'} = $ARGV[0]));
@get = split(/&/, $ENV{'QUERY_STRING'});#---パラメータ解釈
foreach (@get) { ($x ,$y) = split(/=/, $_);$qs{"$x"} = $y;} 
print "p1= $qs{p1}<BR>\np2= $qs{p2}<BR>\nARGV = $ARGV[0]";