PHP を CGI モードで動かす

no extension

めったにないんだけど, 仕事で PHP で pcntl extension を使う必要が出てきて (そういう仕事なんだってば) やってみたんだけど, shell 上の単体テストレベルではちゃんと動くのに Web 上に乗っけると 「pcntl_fork ? なんじゃそら?」(←かなり意訳)って怒られる。 調べてみたら「pcntl 使いたいなら CGI モードで動かさんかい!」(←超意訳)っちうことらしい。

ほら, 仕事で PHP 使うなんて滅多にないし, 放っといたらすぐに忘れてまた同じところで悩むに決まってるので, 覚え書きとして残しておくことにする。

同じようなことで悩んでいる人はそこそこいるらしく色々と情報を得ることができた。 以下に参考になったページを挙げておく。

分かってしまえば PHP を CGI モードで動かすことはそれほど難しくはない。 「CGI バイナリとしてインストール」では4つのケースを紹介しているけど, ここでは「ケース 2: --enable-force-cgi-redirect を使用」を適用してみる。

このやり方は制限があって

「このオプションは、Apache Web サーバーでのみテストされており、 リクエストのリダイレクト時に Apache が標準ではないCGI 環境変数 REDIRECT_STATUS をセットすることを前提にしています。 リクエストが直接のものであるか間接のものであるかを示す手段をWeb サーバーが全くサポートしていない場合は、 このオプションを使用することはできません。」

となっている。 もちろん CGI モードを使うことでサーバ内の任意の場所を「実行」されては困るわけで, この制限は妥当といえる。 ただしそれも Web サーバの設定次第でどうにでもなってしまうので, 構成の検討は慎重に行うべきだろう。

httpd.conf を眺めると以下の記述がある。

ScriptAlias /cgi-bin/ /usr/local/apache2/cgi-bin/

ScriptAlias ディレクティブは CGI プログラムの場所を示すもので

「ScriptAlias が接頭辞で始まるすべての URL は CGI プログラムとみなされるという追加の意味を含んでいることです。 従って、上記の例では、/cgi-bin/ で始まるリソースへのあらゆるリクエストに対して、ディレクトリ /usr/local/apache2/cgi-bin/ から提供し、 それらを CGI プログラムとして扱うよう Apache に示します。」 (「CGI による動的コンテンツ」

つまり, 上記の例では /usr/local/apache2/cgi-bin/ に php-cgi を放り込んでやればいいわけだ。 私の場合, ここではまってしまった。 単純にコピーすればいいものを ln -s とかやっちまったのだ。 どうやっても動かなくてひとしきり悩んでしまった。

さて, もちろんこれだけで CGI モードで動くわけではなく, CGI モジュールの指定と CGI が動くディレクトリを指定してやらなければならない。 例えば http://foobar/hoge/ 以下のディレクトリで PHP を CGI モードで動かしたいなら,

<Directory /hoge>
   Options +ExecCGI
   Action php-script /cgi-bin/php-cgi
   AddHandler php-script .php
</Directory>

と記述する。 Options ディレクティブで CGI の使用許可を, Action ディレクティブで CGI モジュールの指定を, AddHandler ディレクティブでハンドラを指定する。

この記述は httpd.conf で行うが, レンタルサーバでは httpd.conf にアクセスできないのが普通なので, (許可されていれば) .htaccess に AddHandler を記述することで CGI モードが有効になる場合もあるらしい。

AddHandler application/x-httpd-phpcgi .php

ここまで設定しておけば, たとえば http://foobar/hoge/script.php と打つと, http://foobar/cgi-bin/php-cgi/hoge/script.php とリダイレクトされ, さらに /hoge/script.php のアクセス制限をチェックしてくれる。

おー,こんびにえんす!