肉とビールとパンケーキ by @sotarok

少し大人になった「肉とご飯と甘いもの」

phpenv + php-build を使って 5.3 と 5.4 を共存させつつ php-fpm を使う

っていう話なんですが、前提として、 phpenv + php-build は他にも多くの方が語ってるので、そちらを参考に。いやむしろ僕も参考にさせていただきました、ありがとうございます、いくら安いとはいえこれで PHP 5.4 のためにVPS1台借りるとかってことがなくなってよかったです。というか @yuya_takeyama さんのおかげですありがとうございます。


なんですが、えーっと、作るのはだいたいWebアプリで、cli の php が複数バージョンいれられるのは大変嬉しいけどそれだけだと PHP 5.4 なら built-in server があるからいいけど PHP 5.3 の開発とか困るねってことで、php-fpm も入れたいと思います。


流れ

  • enable-fpm で php-build する
  • そんな fpm プロセスを立ち上げる
  • nginx とか設定する

enable-fpm で php-build する

まず、php-build むけのカスタムな設定をつくります。5.4.0s でつくります。s-suffix は sotarok の s です。

$ v ~/.php-build/share/php-build/definitions/5.4.0s

内容はこんなかんじ。全部入りです。configure_option をいじるんですけど、 --enable-fpm だけあればいいんですけど、 --with-mysql-sock=/tmp/mysql.sock とかいれてるのは好みの問題なので、いれなくても良いはずです。

configure_option "--enable-fpm --enable-fileinfo --enable-hash --enable-json --enable-sysvsem --enable-sysvshm --enable-sysvmsg --enable-bcmath --with-bz2 --enable-ctype --with-iconv --enable-ftp --with-gettext --enable-mbstring --with-onig=/usr --with-pcre-regex --with-mysql=mysqlnd --with-mysql-sock=/tmp/mysql.sock --enable-phar --enable-shmop --enable-sockets --enable-simplexml --enable-dom --with-libxml-dir=/usr --enable-tokenizer --with-zlib --with-kerberos=/usr --with-openssl=/usr --enable-soap --enable-zip --with-mhash=yes --without-mm --with-enchant=/usr --with-zlib-dir=/usr --with-gd --enable-gd-native-ttf --with-gmp=/usr --with-jpeg-dir=/usr --with-xpm-dir=/usr/X11R6 --with-png-dir=/usr --with-freetype-dir=/usr --with-imap=/usr --with-imap-ssl --enable-intl --with-t1lib=/usr --with-mcrypt=/usr --with-snmp=/usr"
install_package "http://www.php.net/distributions/php-5.4.0.tar.bz2"
install_pyrus
install_xdebug_master

で、これを指定してインストール

$ php-build 5.4.0s ~/.phpenv/versions/5.4.0s


ところで、そういえば、php-build が install_pyrus でコケる現象が前あって、デバッグってことで install_pyrus まわりにログを仕込んでると動いたりしてなんか原因が特定できなかったです。
ちなみに、install_pyrus って php ビルドした後に実行されるんでが、これにコケると、php 本体の make は成功してるのにこれまるごと cleanup されちゃうっていう仕様になってて悲しい思いをしたので、 cleanup 処理はコメントアウトしちゃってます。

~/.php-build/bin/php-build

428 # Handles build errors, and displays the last 10 lines
429 # of the build log.
430 function build_error {
431     {
432         echo
433         echo "BUILD ERROR"
434         echo $(tail -n10 "$LOG_PATH")
435         echo
436         echo "The full Log is available here ${LOG_PATH}"
437         echo
438     } >&3
439
440     # Removes the prefix when the build fails.
441     #cleanup_abort # ←ここをコメントアウトしてる
442 }

PHP-FPM の設定

話がそれました。
で、php-fpm つきでビルドができると、以下のように sbin/php-fpm が生成されます。

$ ls -la .phpenv/versions/5.4.0s/sbin/php-fpm
-rwxr-xr-x 1 sotarok sotarok 31055874 2012-05-02 00:38 .phpenv/versions/5.4.0s/sbin/php-fpm

こいつをおもむろに実行してみると、

$ cd .phpenv/versions/5.4.0s
$ ./sbin/php-fpm
[22-May-2012 16:16:27] ERROR: failed to open configuration file '/home/sotarok/.phpenv/versions/5.4.0s/etc/php-fpm.conf': No such file or directory (2)
[22-May-2012 16:16:27] ERROR: failed to load configuration file '/home/sotarok/.phpenv/versions/5.4.0s/etc/php-fpm.conf'
[22-May-2012 16:16:27] ERROR: FPM initialization failed

php-fpm.conf つくらなきゃいけない感じがします。(php-build でなんかひっかけてつくればいいんですよね多分、面倒だから見てないけど、多分そう。)

ってことで、 ~/.phpenv/versions/5.4.0s/etc/php-fpm.conf に 適当にファイルを作成します。

  • https://gist.github.com/2767859
    • path とか適当に変えてください。
    • デバッグのために、 daemonize = no とかに設定してます。このほうが再起動とか楽なので。で、そうするとターミナルとられちゃうんですけど、どっちにしろ screen で1つわりあてちゃえばいいだけのはなしです
    • listen を 127.0.0.1:9002 とかにしてます

あとは... あ、あとそうだ、なんか適当な位置にログをおきます。もし ~/var/log とかなかったらつくってください

で、起動!

$ ~/.phpenv/versions/5.4.0s/sbin/php-fpm
[22-May-2012 18:44:48] WARNING: [pool www] 'user' directive is ignored when FPM is not running as root
[22-May-2012 18:44:48] WARNING: [pool www] 'group' directive is ignored when FPM is not running as root
[22-May-2012 18:44:48] NOTICE: fpm is running, pid 787
[22-May-2012 18:44:48] NOTICE: ready to handle connections

pool の user, group は root じゃないとうごかないよーって警告でるんですが、コメントアウトすると、起動しないです。root では動かさないので、まぁ、適当です。

で、これで fastcgi で受け付ける準備ができました。

nginx の設定とか

127.0.0.1:9002 で受け付ける upstream を定義します。

upstream php54 {
    server 127.0.0.1:9002;
}

# {{{ z.merlot.strk.jp;
server {
  listen 80;
  server_name z.merlot.strk.jp;
  index index.php;
  root /usr/local/var/www/z.merlot.strk.jp/public;

  location / {
    if (!-e $request_filename) {
      rewrite ^(.*)$ /index.php$1 last;
    }
  }

  location ~ \.php.*$ {
    fastcgi_split_path_info ^(.+\.php)(.*)$;
    fastcgi_pass php54;
    fastcgi_index index.php;
    include /etc/nginx/fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_param PATH_INFO $fastcgi_path_info;
    fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info;
  }
}
# }}}

で、再起動。

z.merlot.strk.jp にアクセスすると、

あとは

5.3.13 とかも同じ方法でつくって、fpm は listen port かえて、nginx の設定で、こいつを指定すればいいですね。

upstream php53 {
    server 127.0.0.1:9003;
}
# {{{ p.merlot.strk.jp;
server {
  listen 80;
  server_name p.merlot.strk.jp;

  # .. (snip)

  location ~ \.php.*$ {
    # .. (snip)
    fastcgi_pass php53;
    # .. (snip)
  }
}
# }}}


これで快適に fpm 環境のテストもできるし、phpenv つかったものの、phpenv でバージョンを切り替える必要すらなく、port を指定して別の php-fpm プロセスをたちあげておけば、幸せに複数バージョンで開発をすすめられるし、ホスト別に分けるのはもう nginx の設定で適当にすればいいので、楽チンです。

enjoy it!