[ トップページ / Comp / CGI / FAQ ]

CGIのFAQ



Q.
CGIスクリプトが間違っているらしいのですが、ブラウザには「Server Error」としか表示されません。スクリプトの詳しいエラーを見る方法はないのでしょうか。
A.
まず、シェルからCGIスクリプトを実行してみましょう。構文エラーならそのエラーが端末に出力されるはずです。
うまく行かないなら、環境変数(REQUEST_METHODやQUERY_STRING)を、CGIスクリプトが実際に実行される時と同じように設定して試してみるとよいでしょう。
例 : (1行目は/bin/cshを起動しているだけです)
$ csh↓
% setenv REQUEST_METHOD GET↓
% setenv QUERY_STRING key=data&key2=date2↓
% test.cgi↓
NCSA系のHTTPサーバーは、CGIスクリプトのエラー(正確には標準エラー出力-STDERRから出力された文字列)を、httpd.confで指定されたログディレクトリ中の「error.log」(NCSA、Apache〜1.2のデフォルトは/usr/local/etc/httpd/log/error.log。Apache1.3〜のデフォルトは/usr/local/apache/log/error.log)に出力する、上記の方法でだめな方は、このファイルを見てください。
このファイルを見る権限のない方は、CGIスクリプトの先頭に以下のコードを埋め込むとよいでしょう。ただしこれはperl5以降でのみ有効で、さらにBEGIN構文を解釈する前のエラーについては無効です。
BEGIN{
	close(STDERR);
	open(STDERR,">>your-own-log-dir/error.log");
}
END{
	close(STDERR);
}

Q.
Proxyを通しているプロバイダでCGIを動かしたの場合、環境変数REMOTE_ADDRで得られる情報はproxy(bbb.bbb.bbb.bbb)の情報になりますよね。
私が知りたいのは、proxyの本当のリモートアドレス(aaa.aaa.aaa.aaa) のところなんです。つまり何処の情報をフォワードしているか 知りたいのです。
A.
$ENV{'HTTP_FORWARDED'}などで調べます。squidでは、
http://xxx.xx.xx.xx.jp:80/ (Squid/1.0.22) for aaa.aaa.aaa.aaa
と出ます。ユーザのIPがaaa.aaa.aaa.aaaで、間にSquidを使ってるのが分かります。 $ENV{'HTTP_USER_AGENT'}にも
Mozilla/3.04 (WinNT; I) via Squid Cache version 1.0.22
てな感じでSquidのバージョンが出てきます。 ためしに一度、
#!/usr/local/bin/perl
print "Content-Type:text/html\n\n";
foreach(sort keys %ENV){
        print "$_:$ENV{$_}
"; }
のようなCGIスクリプトを動かしてみてはいかがでしょう?いろんな 環境変数が見られると思います。

ただし、CGIスクリプトが受け取る環境変数のうち、頭に"HTTP_"が付くものは、ブラウザやProxyの自己申告なので、簡単に偽造できることを覚えておきましょう。これで本当の通信相手のIPアドレスが分かるとは限りません。


Q.
雑誌の通りにプログラムを打ち込んだのに、まったく動きません。どうしてでしょうか?
A.
まず、打ち間違いを疑いましょう。打ち間違いがないと思っても、案外変なところに間違いはあるものです。 特に、"と'や、;と:の間違い、ゼロとオーの間違いなどに気をつけましょう。 また、初心者がよくやる過ちは、実行フラグを立てずにいることです。シェルから次のコマンドを入力して実行フラグを立ててやりましょう。
chmod a+x CGIスクリプト名
次に、UNIX系のマシンでCGIスクリプトを動かしている場合、行末コードがLF(\n)になっているか気をつけましょう。MacやWindowsのTeachTextやメモ帳で書いたCGIスクリプトをそのままFTPでUNIXに持っていってもきちんと動きません。 MacやWindowsには行末コードを変換するフリーソフトがたくさん出ているので、これらを使うか、Emacsを使って修正しましょう。 Emacsでは、
M-x M-k f *euc-japan*unix
と入力することによって、UNIXのEUCに変換できます。 あるいは、以下のPerlスクリプトを使っても修正できます。
#/usr/local/bin/perl -p
# ↑あなたのサーバーのperlのパス
#
# macwin2unix:標準入力の改行コードをLFに変換して標準出力に出力する

s/\r\n/\n/;
s/\r/\n/;
さらに、漢字コードの問題もあります。シフトJISやJISの中には、Perlが解釈しうる文字(#や%など)が入っているおそれがあるので、これらの漢字コードを使っている場合には、Emacsなどを使って(上記参照)EUCに変換してやるか、jperlという日本語対応版のperlを使いましょう。 また、雑誌などに書いてあるperlのパスはたいてい/usr/local/bin/perlになっていますが、/usr/bin/perlにperlをインストールすることもありますので、
which perl
などを実行して、perlのパスを調べてやりましょう。違っていたらCGIスクリプトの1行目を修正すればOKです。 ほとんどの場合はperlのパスは/usr/local/bin/perl/usr/bin/perlのどちらかなので、どちらにもない場合はperlがそもそもインストールされていない可能性の方が高いです。管理者にカニ缶でも贈って便宜してもらいましょう。

Q.
エラーの原因が分かりません
A.
エラーの原因はいろいろあります。上記のエラー・ログの読み方を読んで、しっかり追求してください。
とはいえ、サーバー・エラー(Server Error)の原因のほとんどは、構文ミスやdie文でプログラムが強制終了してしまった場合です。どちらでもないと確信した場合は、Content-Type行のミスや、Content-Type行(というかHTTPヘッダ)の出力の前になにか出力してしまっていることを疑いましょう。
エラー
print "Contenet-Type: /text/plain\n\n"; # Contentのつづりが違う
print "Hello World!!";
エラー
print "Content-Type: /text/plain\n"; # \nが一つしかない
print "Hello World!!";
エラー
print "hello!!"; # HTTPヘッダの前に出力をしてはいけない
print "Content-Type: /text/plain\n\n";
print "World!!";

Q.
日本語で正規表現を行いたいのですが
A.
方法はいろいろありますが、ケース・バイ・ケースですし、あまり奇麗な方法はありません。jperlという日本語対応のperlをインストールするのが一番のようです。

Q.
ゲストブックを作ったのですが、どうも文字化けしてしまいます。
A.
ユーザーから送られた日本語をそのままCGIの出力に使うと、EUCやシフトJISなどの漢字コードが混在して文字化けを起こします。漢字コードの統一を行いましょう。
漢字コードの変換は、nkfやqkcなどの外部コマンドや、jcode.plというフリーのライブラリを使用して行います。
EUCでCGIの出力を行うと多くのPC用ブラウザで文字化けするので、出力にはシフトJISかJISを使いましょう。
また、1バイトかな文字(俗に言う半角カナ)は文字化けの原因となります。なるべく使わないようにユーザーをしっかり啓蒙した上で、jcode.plについている、1バイトかな文字--2バイトかな文字変換関数を使って対策を取りましょう。

Q.
0x0d(\n)を出力したいのですが、なぜか0x0d(\r\n)が出力されてしまいます。
A.
お使いのPerlは多分Windows版かDOS版でしょう。これらの版のPerlは、自動的に"\nや"0x0d文字などを"\r\n"に変換してしまいます。以下のように、ファイルハンドルに対してbinmode()を実行すればOKです。
print "\n"; # 0x0a,0x0dを表示
binmode(STDOUT);
print "\n"; # 0x0dを表示

Q.
ユーザのホームディレクトリを知るために、"~user"を展開したいのですが、どうすればいいのでしょうか?
A.
次の2つの方法で展開できます。
$user = 'someone';
$home = <~$user>;
または、
$user = 'someone';
$home = ((getpwnam($user))[7]);#($[ == 0の場合)。

Q.
メールのタイトルを復号化したいのですが、どうすればよいでしょうか?
A.
もしnkfを持っていれば、
open(FILE, "/usr/local/bin/nkf -em $file |");# /usr/local/bin/にnkfがある場合
のようにすれば復号化できます。この場合では文字コードはEUCになります。

Q.
jcode.plがうまく動きません
A.
jperlと一緒に使っていないでしょうか?jperlとjcode.plを一緒に使うとうまくスクリプトが動かないようです。

[ トップページ / Comp / CGI / FAQ ]