Back to page

− Links

 Print 

Gentoo Linuxな生活​/複数バージョンのPHP同時起動で悩む :: Nest Of Hawk

xpwiki:Gentoo Linuxな生活/複数バージョンのPHP同時起動で悩む

Table of contents
  • 違うバージョンのPHPを動かしたい!
  • どうやって複数バージョンのPHPを共有させるか
  • 準備
    • PHPのビルド
    • Apacheのビルド
  • 動作設定
    • Apache側
    • PHP側
      • 起動PHPの指定
      • PHP7.1側の設定
      • PHP5.6側の設定
    • Apache側のFPM動作の設定
  • プロセス起動
  • 使用するPHPバージョンの宣言

違うバージョンのPHPを動かしたい! anchor.png[1]

Webアプリを運用していると、開発が活発なアプリ、あまり更新されないアプリで、動作要件が変わってきたりします。特に大きいのは、Webアプリを動作させる肝となる、シェル言語のバージョン。で、軽量なWebアプリでメジャーな言語はPHP。このPHPって曲者で。バージョンアップでかなり言語仕様が変わります。なもので…最近PHP5じゃないと動かないアプリと、PHP5のサポートを終了させようとしているアプリが入り乱れてきました。なもので、古いアプリはPHP5、新しいアプリはPHP7で動かす環境を作らないといけなくなってまいりました。でも、Webサーバ(Apacheやnginx等)を複数動かすのはとてもうれしくない。なので、Apache一つで、Webアプリによって動作させるPHPを分けて見るようにします。

では、行ってみましょう

Page Top

どうやって複数バージョンのPHPを共有させるか anchor.png[2]

ApacheでPHPで記述されたWebアプリを駆動するには、以下の手順が使えます。

  1. モジュール
  2. CGI
  3. FastCGI

モジュールの場合は、mod_phpを用いて、Apacheのプロセス内でPHPの処理を実行します。

CGIは、Apacheから、HTTPリクエストがあるたびにPHPのプロセスを起動して、PHPスクリプトを実行します。

FastCGIは、PHPのプロセスを予め起動させておき、ApacheにHTTPリクエストが来るたびに、TCPもしくはUnix Dmain Socket経由で常駐PHPプロセスに処理をさせます。

この中で、GCI方式が最も重そうな方法であることはご理解いただけるかと。mod_phpが最もシンプルな方法なのですが、1つのバージョンしか使えない。なので、FastCGIで複数バージョンを同時駆動させる方法を採用することとします。

Page Top

準備 anchor.png[3]

Page Top

PHPのビルド anchor.png[4]

  • PHPのUSEフラグに"fpm"を追加します。
  • make.confに以下の記述を追加します。
    PHP_TARGETS="php5-6 php7-1"

ここのPHP_TARGETSは、インストールしておきたいバージョンのPHPを列挙します。私はPHP5系の最新(php5-6)と、PHP7系の最新(php7-1)を書いておきます。

  • emergeします。

おしまい。

Page Top

Apacheのビルド anchor.png[5]

  • make.confのAPACHE2_MODULESに、"proxy proxy_fcgi"を追記します。
  • emergeします。

おしまい。

Page Top

動作設定 anchor.png[6]

モジュールによる起動は既にできていることとします。このため、FastCGIにて起動する方法を中心に記載します。

ApacheのFCGI Proxyモジュールを用いて、バックエンドのPHPと通信致します。

Page Top

Apache側 anchor.png[7]

/etc/conf.d/apache2内のAPACHE2_OPTSに、以下の定義を追記します

-D PHP -D PROXY
Page Top

PHP側 anchor.png[8]

Page Top

起動PHPの指定 anchor.png[9]

今回は、以下の設定とします。

  • FastCGIのデフォルトはPHP7.1
  • さらにもう一つFastCGIのPHP5.6を駆動する

起動するバージョンを設定してやります。

# eselect php set fpm php7.1

さらに、普通に設定すると、FPM版PHPの起動シェルは1つしかありません。eselectで指定したバージョンを起動してくれます。ので、指定バージョンを起動するシェルを作ってあげます。

# cd /etc/init.d
# cp php-fim php-fpm5.6
# vi php-fpm5.6

さて、このコピーしたphp-fpm5.6の頭にある以下の部分を修正します。

PHP_SLOT="${SVCNAME#php-fpm-}"
                  ↓
PHP_SLOT="php5.6"

eselectで指定するphpのバージョン名ね

Page Top

PHP7.1側の設定 anchor.png[10]

/etc/php/fpm-php7.1/fpm.d/www.confを編集します。今回は、UNIXドメインソケットで通信出来るように設定します。以下の項を注意して設定します。

user = nobody                        # FPM版のPHPの起動ユーザ権限
group = nobody                       # FPM版のPHPの起動グループ権限
listen = /var/run/php-fpm/www.sock   # 通信するポートを指定。ここではwww.sockというUNIXドメインソケットを指定
listen.owner = nobody                # 上記ソケットのユーザ
listen.group = nobody                # 上記ソケットのグループ
listen.mode = 0660                   # 上記ソケットのアクセス権

特に起動ユーザ、グループ、ソケットのユーザ、グループ、アクセス権は注意して設定してくださいね。Apacheの起動ユーザ権限とソケットのアクセス権が合っていないと、「Permission Denied」と言われます。また、PHP-FPMの起動ユーザ、グループがWebアプリ側のアクセス権と合っていないと、PHP-FPM側は、Webアプリファイルにアクセス出来ないと言われます。apacheのerror_logをよく見ててくださいね~

Page Top

PHP5.6側の設定 anchor.png[11]

/etc/php/fpm-php5.6/php-fpm.confを編集します。今回は、UNIXドメインソケットで通信出来るように設定します。以下の項を注意して設定します。

user = nobody                        # FPM版のPHPの起動ユーザ権限
group = nobody                       # FPM版のPHPの起動グループ権限
listen = /var/run/php-fpm/www5.6.sock   # 通信するポートを指定。ここではwww5.6.sockというUNIXドメインソケットを指定
listen.owner = nobody                # 上記ソケットのユーザ
listen.group = nobody                # 上記ソケットのグループ
listen.mode = 0660                   # 上記ソケットのアクセス権

7.1のときと設定の注意は変わりませんが、ポイントは、listen=で作るソケットの名称です。バージョン名で分けると。

Page Top

Apache側のFPM動作の設定 anchor.png[12]

/etc/apache2/70_mod_php.confを以下のように記載。

<IfDefine PHP>
       <FilesMatch "\.php$">
               SetHandler "proxy:unix:/var/run/php-fpm/www.sock|fcgi://localhost"
       </FilesMatch>

       # Set it to handle the files
       <IfModule mod_mime.c>
               AddHandler application/x-httpd-php .php .php5 .phtml
               AddHandler application/x-httpd-php-source .phps
       </IfModule>

       DirectoryIndex index.php index.phtml
</IfDefine>

起動オプションにPHPが指定されていたら、拡張子.phpにマッチするファイルは、PHP-FPMのソケットに渡す、というエントリーです。

Page Top

プロセス起動 anchor.png[13]

ApacheとPHP-FPMを再起動します。

# /etc/init.d/apache2 restart
# /etc/init.d/php-fpm restart
# /etc/init.d/php-fpm5.6 restart
Page Top

使用するPHPバージョンの宣言 anchor.png[14]

  • 古いバージョンで起動させたいWebアプリだけ、.htaccessで制御する

と、言うことで、各Webアプリは、ディレクトリで別れて格納されいると仮定します。PHP5.6で動かしたいWebアプリが格納されているディレクトリのトップに、.htaccessを置き、以下の内容を追記します。

<IfDefine PHP>
   <FilesMatch "\.php$">
       SetHandler "proxy:unix:/var/run/php-fpm/www5.6.sock|fcgi://localhost"
   </FilesMatch>

   DirectoryIndex index.php index.phtml

</IfDefine>

.htaccessは、置かれたディレクトリ配下のアクセス条件に上書きされるので、このエントリーがある.htaccessがあるWebアプリはwww5.6.sockで通信される。PHP5.6で動く、という仕掛け。

もうおわかりかと思いますが。起動シェルをコピーして、ソケット名を分けていけば、いくつでもPHPが起動できると言うわけですね。

これで、PHPバージョンでアプリが動かなくなる悪夢から解放されそうです♪


Last-modified: 2018-02-17 (Sat) 20:49:50 (JST) (1681d) by maruo