エラー捕捉や例外捕捉の機能を使って、何らかのエラーが発生したらトラップするようにしておく。
そして、エラーをトラップしたら、以下の動作を行うようにする。
- 自分にメールで通知(可能なら、CGIパラメータやスタックダンプ等、デバッグに役立ちそうな情報もつける)
- ユーザには、「ただいまメンテ中です」とか、適当なメッセージを見せる
コレをやっておかないと、何らかのトラブルが発生した時には、きっと手遅れになる。
逆に言えば、コレをやっておけば、(顧客にとっての)被害を最小限に抑えられる。
また、コレを行うという事は、「納品したら終わり」ではなく、「運用期間中はシステム/コードの、メンテ/サポートを続ける=サポート期間中も金を取る」というスタイルになるので、予めそういうものだと顧客側に理解してもらっておく必要がある(が、コレがかなり厳しかったりもするが)。
コレが出来れば、顧客とのトラブルは大幅に減る筈。
- Gauche?なら、www.cgiのcgi-mainの:on-errorキーワードを使えば、簡単に実現できる。
- しかし、cgi-main外でのエラーは捕捉してくれない(例えば、cgi-mainの前にDBに接続する際にDBが死んでたり、とか)ので、其処はちょっと工夫する必要がある。
- Location: ヘッダには、#fragment部分をつけてはいけない。
- rfc2616で規定されているっぽい。以下のabsoluteURIの部分より。
- CGI?が、副作用を伴う動作を行う場合、実行後はHTML等を表示せずに、一旦Location:ヘッダ等を使って、リダイレクトするようにする。
- こうすれば、ブラウザの履歴で戻った時に、もう一度実行されてしまう事は無い。
- 但し、この場合も、下記のLocation問題に注意する事(slashから始まるpathを与えると、予想した通りに動作しなくなる)。
- apache?では、http等のscheme名から始まらず、/から始まるuriへのLocationは、リクエストは外に投げられずに、そのまま内部で処理され、Location先のコンテンツが直にクライアントに送られる。
- この為、例えば、
http://hoge.com/cgi-bin/location.cgi
が、「Location: /hoge/index.html」を投げた場合、apache?は内部でそれを処理し、直接クライアントに
http://hoge.com/hoge/index.html
のコンテンツを返す事になる。
- しかし、クライアントから見たuriは、まだ
http://hoge.com/cgi-bin/location.cgi
のままなので、index.htmlの中で、例えば、「<a href="hoge.html">」等とリンクがあった場合、このリンクは
http://hoge.com/hoge/hoge.html
ではなく、
http://hoge.com/cgi-bin/hoge.html
へとアクセスされてしまう事になってしまう。
- 但し、「Location: ./file.html」等のような相対pathを指定した場合は、apacheは何も解決せずに、これを外部に送ってしまう(rfc違反/この際の挙動はクライアント依存)。
- 妙なアクセスログが残っている時は、これが原因かも知れない。
- このような問題を避ける為には、極力Location時のuriは、scheme名で始まるuriを指定するようにすれば良い。
- 一般的に、FastCGI対応モジュールを使ったスクリプトは、通常のCGI?としても動作するが、逆は動かない(スクリプトのSTDOUTは全てhttpdのSTDERR(エラーログ)に流れる)。
- mod_asisの怪しい使い方
- 以下のようなスクリプトを書き、cronで定時実行させる
#!/bin/sh
# 必要なら、適当に環境変数を設定しておく
export REQUEST_METHOD=GET
export HTTP_HOGE=hoge
cd /path/to/cgi-dir
perl hoge.cgi > /path/to/tmp/index.asis.new &&
mv /path/to/tmp/index.asis.new /path/to/htdocs/index.asis
- SIGPIPEの脅威
- CGI?スクリプトへのアクセス中にブラウザから「中断」とか、そんなのを押すと、その時点でソケット通信が切れて、SIGPIPEが発生する。
- 素のCGI?の場合、SIGPIPEハンドラを設定していない限り、普通に途中終了されると思う(デフォルトのSIGPIPEハンドラ動作として)。
- FastCGIで動作している場合は、モジュールがSIGPIPEハンドラを上書きして大丈夫になっている可能性もあるが、そうでなければ途中終了する。
- 両方の場合を考えて、自前でSIGPIPE対策を行っておいた方が無難。
- 現在、普通にhttpで通信しているか、SSLを使ってhttpsで通信しているかを判定するには、通常、メタ変数HTTPSの有無で判定する。
- しかし、big-ip等を使って、途中経路からSSLをかけている場合は、この方法では判定できない。
- その場合は、スクリプト側が、メタ変数SERVER_PORTが何番かで判定するのが手軽(何故なら、big-ip等でSSLをかける場合、80番以外を使う事が多い為)。
- 真面目にやる場合は、httpd.conf等で、「SetEnv HTTPS on」としてメタ変数HTTPSを設定するようにすれば、スクリプト側はいじらなくてすむ。
- CGI周りはライブラリ/モジュール化されていて、このSSLの判定もライブラリ内で行うのが普通だと思うので、その場合はhttpd.conf等で「SetEnv HTTPS on」した方が安全。
最終更新 : 2006/11/06 20:23:40 JST