綾小路龍之介の素人思考

[perl] Perl > サーバーにアップロードしたcgiのエラーチェック

「cgiはローカルで動作確認済みのものをアップロードしてください。」共有サーバに無用な負担がかかるのを防ぐために規約にかかれている文言だ。つまり、サーバにおける正常な動作が保証されていないスクリプトは、サーバで走らせてはいけない、ということだ。ローカルで正常動作したものが、サーバで正常動作するという保証は無い。なぜなら、ローカルとサーバでは環境が異なるからだ。では動作確認をどのようにすればいいのだろうか。サーバ上での正常動作を保証するには、サーバ上で動作確認するしかあるまい。なぜなら、正常な動作の保証は実行環境とテスト環境が全く同じであるからこそなされるからだ。この項では、Perlで書かれたcgiプログラムの異常終了を正常終了したものとし、エラーメッセージを表示するサブルーチンの導入を行うことで、サーバ上でも動作の確認ができるようにする。

目次

cgiのエラー云々の前に

エラーが出力されるようにせねば。まぁ致命的なエラーは何もしなくても出力されるんだけども、致命的なエラーはcgiが動かないのとほとんど同じ。まずはスクリプト1行目に下のようにおまじないを書いた。こう書けば、些細なことも注意してくれる。そのほうが、効率的なプログラムが書けるはずだ。gcc -Wallみたいなものだ。でもこのままでは、些細な注意のたびにcgiプログラムは終了してしまい、エラーがトレースできない。

#!/usr/local/bin/perl -wT

そこで、次の手段だ。CGI::Crapを使って、出力されたエラーをHTMLで書き出すようにする。

[wget] cgiの結果をwgetで取得

いちいちtelnetでhttpコマンドしゃべっていられんという場合には、cgiの結果をwgetで取得するといいかもしれない。HTTPレスポンスヘッダを標準出力する場合には-Sオプションを付ける。もう何でも表示してくれという場合はデバッグオプションである-dを付ける。デバッグオプションをつければ、リクエストヘッダ、レスポンスヘッダなどが標準出力される。cgiのエラーはHTTPヘッダにかかれるようなので、プロンプトにエラーが出力される。

$ wget -O /dev/null -d http://example.com/cgi-bin/hoge.cgi

perlで普通にlocationヘッダを出力するとiswebのサーバの場合は302が返る。301を返すために下のようにしてみたらそもそもページ遷移しなかった。

print "Status: 301 Moved Permanently\n";
print "Location: http://www.yahoo.co.jp/\n\n";

cgiの結果をtelnetクライアントで取得

telnetクライアントにHTTP要求を喋らせようということである。だからcgiの結果をtelnetで取得するという表現には違和感を覚える。なんとなくだけど。telnetというのはサービス、telnetクライアントはこのサービスに接続できるクライアントのこと。僕らはhttpサーバに接続するわけで、telnetサービスを提供しているtelnetサーバに接続するわけではないのだから、telnetクライアントの持つサーバとお喋りする機能を流用してhttpサーバとお喋りしようということなんじゃないかな。口上はこの程度にしておきましょう。

wgetを-Sオプションつきで呼び出すのもいいけれど、このとき画面に出力された内容がwgetによって加工されていないとも限らない。httpヘッダを覗く最もプリミティブな方法はtelnetを使う方法である。コマンドラインから下のようにコマンドを叩く。最後に2回改行するのを忘れない。あと、改行はCR+LFで送信するように設定。cgiのエラーは標準出力に出力されるので(多分)、受信するレスポンスヘッダ以降にエラー内容が書き込まれる(多分)。-w付きでcgiを起動させると結構エラーが出る。これをこまめに直すのも一興。

telnet za.toypark.in 80
GET /cgi-bin/foo/bar.cgi?foo+bar HTTP/1.0
Host: za.toypark.in

ここまで書いておいて不親切だと思ったので追記。サーバが受け付ける漢字コードがどんなものか知っているといいけどこれはほとんど問題ではないだろう。つまり僕らが入力した内容をどのような漢字コードでサーバに送出するかという点だ。なぜなら、僕らはいわゆるASCIIコードで定義された文字しか使わないから。UnicodeにせよEUCにせよShift_JISにせよ、多くのコード体系ではASCIIコードを踏襲している、言い換えれば、コード体系の最初の128文字はASCIIコードと被っているということだ。漢字コードの設定が意味を持っている例は、telnetサービスを供給しているサーバで仮想端末からemacsとかviを使って日本語を入力する場合である。

次の注意点はサーバから送られてきたデータの漢字コードである。先に述べたのと同様に、僕らがサーバから受け取った内容が全てASCIIコードの範囲だったら受け取り漢字コードに注意する必要はほとんどないといってもいいだろう。ただし日本語が含まれる結果を出力するcgiを仮想端末で受け取る場合はその結果に即した文字コードを受け取り文字コードとして設定しなければいけない。ブラウザは受け取ったデータから勝手に文字コードを判定して、結果に即した文字コードに変えてくれるからブラウザで受け取り文字コードを明示的に設定する必要はなかったわけだ。どちらにせよここの設定は受けとったデータをどのような漢字コードで書かれたデータと解釈するかという設定である。だから、クライアントが解釈できない文字コードを受け取った場合は、端末にブラウザで表示されるような文字は見えず、文字化けして見える。たとえば、Tera TermはJIS、Shift_JIS、EUC、に対応しているが、Unicodeには対応していないためUTF-8で書かれたWebページを上記の方法で取得しても文字化けして見える。

もう一つ忘れてはいけないことがあった。それは送出改行コードと受け取り改行コードの設定だ。上で送出改行はCR+LFにしろと書いたけど、これには理由があるんだ。理由はhttpの勧告文書にそう書いてあったから。つまり標準化を押し進める団体がそうしろといっているからで、多くのwebサーバはその規格に準拠するように作られているからだ。長いものには巻かれろってことかな。受け取り漢字コードはサーバが送ってきた改行コードを僕らがどう解釈するかという話なんだけど、ここの設定はあまり気にする必要はないと思う。多分、さっき言った標準化団体はサーバから送出されて僕らが受け取るデータも改行コードはCR+LFに決めていたと思う。だから、設定はCR+LFでいいんじゃないかなと思う。

RFCはリファレンスとして最高

わからないことがあったら最もよいリファレンスはRFCなんだな。ここを参照すれば技術的な不明点が明らかになることが多い。下手に検索サイトで探すと時間の割りに実りの少ない結果になることのほうが多い。

RFC2616 : Hypertext Transfer Protocol -- HTTP/1.1
http://www.w3.org/Protocols/rfc2616/rfc2616.html

ソーシャルブックマーク

  1. はてなブックマーク
  2. Google Bookmarks
  3. del.icio.us

ChangeLog

  1. Posted: 2003-11-18T13:39:28+09:00
  2. Modified: 2003-11-18T13:57:56+09:00
  3. Generated: 2017-07-04T23:09:28+09:00