読者です 読者をやめる 読者になる 読者になる

nginxでPHPを動かす

nginx PHP CentOS

業界標準CentOSで皆の大好きなPHPを皆の大好きなnginxで動かす。

大前提としてnginxでPHPを動かすならば選択肢はFastCGIということになる。php-fpmというものがあるらしいが、できるだけ標準・準標準のRPMを使うことを考える。

まず、CentOSの標準のPHPは--enable-fastcgiつきでコンパイルされているのでFastCGIで動かすにあたって特に問題はない。以下のコマンドで確認できる。

$ php -i | grep fastcgi

nginxの設定

なので、nginx側で次のような設定を行い、

server {
  listen 80;
  server_name goto.php.examle.com;

  location / {
    fastcgi_pass   127.0.0.1:8080;
    fastcgi_index  index.php;
    fastcgi_param  SCRIPT_FILENAME /path/to/php/application/$fastcgi_script_name;
    include "/etc/nginx/fastcgi_params";
  }
}

上記のテストとして、

$ sudo -u apache /usr/bin/php-cgi -q -b 127.0.0.1:8080

のようにコマンドラインからFastCGIプロセスを立ち上げれば、ごく普通に皆の大好きなPHPが使えることを確認できると思う。

ポイントは、/etc/nginx/fastcgi_paramsをincludeしているところで、"PHP nginx FastCGI"でぐぐって出てくるこことかここのような設定を参考に最小限のfastcgi_paramを設定しようとしても上手く行かないかもしれないという点である。

僕の場合は、nginxとphp-cgiだけでCactiを動かそうとしたところ、fastcgi_paramの設定が悪くて、Cookieがブラウザに送られないという状況に遭遇した。Fedora系でもdebian系でもきちんとしたnginxのパッケージにはfastcgi_paramsという設定ファイルが含まれているはずなので、これを利用することをお勧めする。

FastCGIプロセスの管理

問題なのは「PHPFastCGIプロセスをどう管理するか」ということである。僕が考えたのは次の二つの選択肢である。

前者の場合はプロセスが死んだ場合に自動的に再起動してくれるというメリットもあるが、個人的にdaemontoolsはそんなに好きではないので、後者の方針をとることにした。

spawn-fcgiは現在は独立したプログラムとして提供されているが、もともとはlighttpdに含まれていたプログラムである。spawn-fcgiだけのRPMがrpmforgeやepelにあれば良かったのだが、適当なRPMが見つからなかったので、rpmforgeのlighttpd-fastcgiパッケージに含まれるspawn-fcgiを使うことにした。

$ sudo yum install lighttpd-fastcgi --enablerepo=rpmforge

【追記】
このエントリを公開した後に探したら、Fedoraにはspawn-fcgiパッケージがあるようだ。

これを使う方がよいかもしれない。

spawn-fcgiを入れたら、/etc/init.d/php-cgiのような名前でinitスクリプトを作成する。

#!/bin/bash
#
# php-fcgi PHP FastCGI daemon
#
# chkconfig: - 85 15
# config: /etc/sysconfig/php-cgi
# pidfile: /var/run/php-cgi.pid

# Source function library.

. /etc/rc.d/init.d/functions

PHP=/usr/bin/php-cgi
PIDFILE=/var/run/php-cgi.pid

HOST=127.0.0.1
PORT=8080
CHILDREN=5
USER=apache
GROUP=apache

if [ -f /etc/sysconfig/php-cgi ]; then
    . /etc/sysconfig/php-cgi
fi

RETVAL=0

case "$1" in
    start)
        echo -n $"Starting php-cgi: "
        daemon --pidfile $PIDFILE spawn-fcgi -u $USER -g $GROUP -f $PHP -a $HOST -p $PORT -C $CHILDREN -P $PIDFILE
        RETVAL=$?
        echo
        [ $RETVAL -eq 0 ] && touch /var/lock/subsys/php-cgi
  ;;
    stop)
        echo -n $"Stopping php-cgi: "
        killproc -p $PIDFILE spawn-fcgi
        RETVAL=$?
        echo
        if [ $RETVAL -eq 0 ] ; then
            rm -f /var/lock/subsys/php-cgi
            rm -f $PIDFILE
        fi
  ;;
    restart)
        stop
        start
  ;;
    status)
        status $PHP
  ;;
    *)
        echo "Usage: php-cgi {start|stop|status|restart}"
        exit 1
  ;;
esac
exit $RETVAL

initスクリプト自体の名前や/etc/sysconfig/*の扱いはお好みで。

その上で、

$ sudo /sbin/service php-cgi start

のようにFastCGIプロセスを立ち上げ、先ほどのnginxで設定したSCRIPT_FILENAMEのパスに、

<?php
phpinfo();

のようなPHPを用意してブラウザからアクセスすればOK。

どうでもいいけど、phpinfo()も僕が好きなPHP関数のひとつです。

PHPを使うならばごく普通にApacheモジュール版を使うのがベストだと思うけど、僕の場合はPython(mod_wsgi)との兼ね合いで、どうしてもどちらかをFastCGIにする(あるいはApacheのプロセスを二つ立ち上げる)という必要があった。この事情もあとで書くかもしれない。