CGI プログラムのはじめの一歩

掲示板を作ろう (1) >> 次へ

hello world

どんな環境でも、最初に作るプログラムは hello world です。 いきなり掲示板を作ろう、なんてのは愚の骨頂。バカのすることです。

hello-world.pl

    1: #!/usr/local/bin/perl
    2: 
    3: print "Content-type: text/html\n\n";
    4: 
    5: print "<html><body>"
    6: print "Hello world.";
    7: print "</body></html>";
動きましたか?

もし動かない場合は

を調べて下さい。

「動きましたか?」と聞いておいてこういうのもアレですが、 このスクリプトは動きません。5行目の print 文の最後に ; が抜けているからです。

これを CGI 経由で動かしてみると

Internal Server Error

The server encountered an internal error or misconfiguration and was unable to complete your request.

Please contact the server administrator, you@your.address and inform them of the time the error occurred, and anything you might have done that may have caused the error.

と表示されます。

人間がプログラムを作ってるんですから、タイプミスをするのは当り前です。 仮にタイプミスをしなくてもロジックのミスで Internal Server Error が 発生することもあります。

見ればわかりますが、このメッセージには 「〜が間違っている」「〜がおかしい」という情報はありません。 とはいえ、目で見てどこが間違っているのかを調べるのはとても困難です。 このスクリプトは 7行しかありませんので不可能ではないでしょうが、数百・数千行の ソースから、手がかりもなく原因を突き止めるのは不可能と言っていいでしょう。

だからといって、他人に「Internal Server Error となってしまうんですけど」と 泣き付かないで下さい。プログラムを作ってるんですから、まずは自分でデバッグしましょう。

デバッグ: perl 編

自分の PC に perl はインストールされていますか? もしなかったら、今すぐインストールして下さい。 FreeBSD・NetBSD・OpenBSD・Linux なら最初から /usr/bin/perl が用意されているはずです。 ただし、OS のバージョンによっては /usr/local/bin/perl を使うべき場合もあります。 ここのスクリプトは perl5 専用ですので、perl4 では動きません (hello world くらいなら perl4 でも動くけど)。

perl をインストールしたら、コマンドラインから

% perl hello-world.pl
として下さい。先のスクリプトだと、
syntax error at hello-world.pl line 6, near "print"
Execution of hello-world.pl aborted due to compilation errors.
となってしまうはずです。「英語だから…」と言ってすぐに他人に 聞こうとする人は、プログラムを作る資格はないので、 CGI プログラムを作るのはあきらめて下さい。

辞書を引きつつ日本語に訳すと、

「hello-world.pl の 6行目、`print' の近くで文法エラーが発生した」 「コンパイル時のエラーが発生したので、hello-world.pl の実行は中断した」
となります。本当は 5行目の最後が問題なのですが、 perl は「6行目の近くが文法エラー」と報告しています。 このように、間違いをずばり指摘してくれないこともあります。 6行目の周辺を地道に探しましょう。

デバッグ: wrapper 編

ローカルでエラーが発生しないのに、CGI 経由で実行するとなぜか エラーが発生してしまう場合があります。

そのような場合には wrapper を使いましょう。

wrapper.pl

    1: #!/usr/local/bin/perl
    2: 
    3: $|=1;
    4: 
    5: print "Content-type: text/plain; charset=EUC-JP\n\n";
    6: 
    7: if ( $ENV{PATH_INFO} eq '' ){
    8:     ($script_name) = $0 =~ m|.*/(.*)|;
    9:     print "foo.cgi をデバッグしたい場合は、\n";
   10:     print "  http://$ENV{SERVER_NAME}$ENV{REQUEST_URI}/foo.cgi\n";
   11:     print "という URL にアクセスして下さい。\n\n";
   12:     print "$script_name の後に / を付けて、さらにデバッグしたいスクリプト名を書くわけです。";
   13:     exit;
   14: }
   15: $file = ".$ENV{PATH_INFO}";
   16: $file =~ s|[^-_\./A-Za-z0-9]||g;
   17: 
   18: $no_good = 0;
   19: if ( ! -e $file ){
   20:     print "ファイル $file が存在しません。\n";
   21:     exit;
   22: }
   23: if ( ! -r $file ){
   24:     print "ファイル $file を読み込めません。\n";
   25:     print "スクリプトは読み込み権限がないと実行できません。\n";
   26:     $no_good = 1;
   27: }
   28: if ( ! -x $file ){
   29:     print "ファイル $file を実行できません。\n";
   30:     print "実行権限が付いていません。パーミッションを 755 や 700 にして下さい。\n";
   31:     $no_good = 1;
   32: }
   33: 
   34: if ( $no_good == 1 ){
   35:     exit;
   36: }
   37: 
   38: print "$file を実行します。\n\n";
   39: 
   40: open(EXEC,"| $file 2>&1");
   41: while (<STDIN>){
   42:     print EXEC;
   43: }
このファイルを wrapper.cgi というファイル名にして、 テストしたい CGI プログラムと同じディレクトリに置いて下さい。 そして、
http://X68000.q-e-d.net/~68user/webcgi/sample/perl/wrapper.cgi/hello-world.cgi
にアクセスして下さい。
./hello-world.cgi を実行します。

syntax error at ./hello-world.cgi line 6, near "print" Execution of ./hello-world.cgi aborted due to compilation errors.

と表示されたはずです。これなら web 経由でエラー箇所を確認できますね。

この URL だと、一見 wrapper.cgi がディレクトリのように思えますが、 WWW サーバはちゃんと wrapper.cgi を実行してくれます。 その際、環境変数 PATH_INFO に /hello-world.cgi という文字列が入っています。

このアクセス方法は便利なのですが、apache 以外の WWW サーバでは 使えない可能性があります (未確認)。

再び hello world

では ; を追加してみましょう。

hello-world-2.cgi (実行結果)

    1: #!/usr/local/bin/perl
    2: 
    3: print "Content-type: text/html\n\n";
    4: 
    5: print "<html><body>";
    6: print "Hello world.";
    7: print "</body></html>";

今度は正しく動きます。

最初に出力している Content-type というのは、 「これから出力するデータの形式」を表します。 「text/html」は、HTML 形式という意味です。 「text/html」のようなデータ形式の指定方法を MIME TYPE と言います。 他にも

など、数多くの MIME TYPE があります。これについては後から詳しく説明します。

ヘッダを出力した後は、'\n' つまり空行 (改行のみの行) を 出力します。これはヘッダの終わりを意味します。 これより後の出力はボディと言います。

掲示板を作ろう (1) >> 次へ