cgi界にはびこる民間療法 Premature end of script headers

cgi界」という言葉があるかどうかは知らないが、「Premature end of script headers」というエラーに対して、都市伝説というか民間療法というか、そういうのがあるようだ。例えば、

#! /usr/bin/perl
。。。。

でこのエラーとなるときに、

#! /usr/bin/perl --
。。。。

とすれば「なぜかわからないが直る」(笑)と書いてある。


そもそも、このメッセージは、「cgiプログラムがContent-Type ヘッダを出力する前に終了した」ということを示すだけであって、ほとんどの場合、その前に本当のエラーメッセージが出ているはずだ。例えば、

(2)No such file or directory: exec of '/var/www/html/test.cgi' failed
Premature end of script headers: test.cgi

で、execが失敗していることがわかる。まあ、これから、#! 行がおかしいことに気づくことができない人も居るだろうけど。


ただ、レンタルサーバーなどで suExec でcgiが動く場合、おそらくエラーメッセージはこのようになる。
例えば、さくらインターネットの共用レンタルサーバーの場合など。

suexec failure: could not open log file
fopen: Permission denied
Premature end of script headers: test.cgi

これは、apacheがユーザ権限で suexec.log に「(2)No such file or directory: exec of '....' failed」のメッセージを書こうとして失敗していることを示すが、これは直感的ににわかりにくい。かといって、/var/log/httpd/suexec.log に全ユーザへの書き込み権限を認めるのも今ひとつだと思うので、できるならapacheに何とかして欲しいところ。


だらだら書いてきたので、Premature end of script headers への対処をまとめておく。

メッセージの意味

cgiプログラムがContent-Type ヘッダを出力する前に終了した

起動に失敗した
現象
次のいずれかのエラーが同時にerror_logに出ている。最後のメッセージの場合は suexec.log に詳細メッセージが出ている。
(2)No such file or directory: exec of '.......' failed
または
suexec failure: could not open log file
fopen: Permission denied
または
suexec policy violation: see suexec log for more details
原因
 
  • #!行のパス名が間違っている
  • 改行コードがDOS(CRLF)になっているので、#!行のCRがパス名にくっついて "/usr/bin/perl\r" などとなってしまっている

(この場合、#!/usr/bin/perl -- とすると\rが離れるので動く*1 → 民間療法)

対応
パス名を正しくする。改行コードをUnix(LF)にする。ファイル・ディレクトリのパーミッションをsuExec環境なら700にそうでなければ755とかに。
起動したがエラーで実行が止まった
現象
PerlなりRubyなりが何らかのエラーメッセージをerror_logに出しているはず。設定によっては何も出ないかもしれない?
原因
スクリプトのバグ
エラーではないが、何も出力せずに終了した*2
現象
他にはエラーメッセージ無し
原因
スクリプトのバグ

*1:PerlRubyでは動くがどんなプログラムでも動くとは限らない

*2:Content-Typeヘッダを出さずに何か出力した場合は、「Premature end of script headers」でなく、「malformed header from script」というエラーになる