気まま研究所ブログ

思ったことをてきとーに書きます。

Raspbianで公式php7をビルド & インストールする

こんにちは。
RaspbianでApache2とPHP5によるウェブサーバーの構築はパッケージツールを用いることで簡単にできることはご存知のことかと思います。
しかし、現在最新版のPHPPHP 7であり、多くのフレームワークはPHP7以上を推奨するようになってきました。
特によく使われるWordpressPHP 7以上を推奨しています。*1
ではPHP7もパッケージツールでインストールできるかというとRaspbian、ひいてはDebianではPHP7のパッケージが配布されていません。
そのため、使用する場合は自身でコンパイルし、インストールする必要があります。
今回はPHP7を構成するにあたって少々詰まったため、構築方法を備忘録的に残しておきます。


はじめに

Raspbianのみならず、Debianでは謎のリポジトリを追加してインストールする方法が広まっていますが、得体の知れないリポジトリから入手するのは非常に気持ちが悪いです。
ですので、今回は公式からソースコードを入手、ビルドし、それをインストールすることにします。
ちなみにですが、Ubuntuでも試したのでほぼ同様の手順で可能ですが、libpng12-devだけlibpng-devに変更する必要があります。
また、Ubuntuの場合はmpmがデフォルトで全て入っているのでそれも不必要です。


Apache 2関連とその他必要なパッケージのインストール

事前に必要なパッケージをインストールしておきます。
ディストリビューション バージョンや今後のPHPアップデートによって必要なパッケージが増加する恐れがありますのでその点はご注意ください。
とりあえず執筆当時最新版のPHP 7.1.7と開発版のPHP7.3.0-devでは以下のパッケージで問題無いと思います。

$ sudo apt-get install apache2 apache2-dev apache2-mpm-prefork
$ sudo apt-get install git \
    autoconf \
    bison \
    re2c \
    libxslt1-dev \
    libcurl4-openssl-dev \
    libssl-dev \
    libbz2-dev \
    libjpeg-dev \
    libpng12-dev \
    libxpm-dev \
    libfreetype6-dev \
    libgmp-dev \
    libmysqlclient-dev \
    libaspell-dev \
    libpspell-dev \
    librecode-dev \
    libmcrypt-dev


PHP 7の入手とビルド

次にPHP7を公式サイト*2からダウンロードし、展開します。
Firefoxで落とす場合は問題ありませんが、wgetなどで落とす場合はmirrorになるのでファイル名を変更しておきましょう。

$ mkdir ~/php7
$ cd ~/php7
$ wget http://jp2.php.net/get/php-7.1.7.tar.gz/from/this/mirror
$ mv mirror php-7.1.7.tar.gz
$ tar zxvf php-7.1.7.tar.gz


展開後、buildconfを実行します。

$ cd php-7.1.7/
$ ./buildconf


続いてビルド用のmakefileを作成します。
オプションについては開発者向けビルドのビルド方法*3とほぼ同じですが、「–with-apxs2=/usr/bin/apxs2」を指定している点に要注意です。
これを入れないとApache2用のモジュールが生成されません。

$ ./configure \
    --prefix=$HOME/tmp/usr \
    --with-config-file-path=$HOME/tmp/usr/etc \
    --enable-mbstring \
    --enable-zip \
    --enable-bcmath \
    --enable-pcntl \
    --enable-ftp \
    --enable-exif \
    --enable-calendar \
    --enable-sysvmsg \
    --enable-sysvsem \
    --enable-sysvshm \
    --enable-wddx \
    --with-curl \
    --with-mcrypt \
    --with-iconv \
    --with-gmp \
    --with-pspell \
    --with-gd \
    --with-jpeg-dir=/usr \
    --with-png-dir=/usr \
    --with-zlib-dir=/usr \
    --with-xpm-dir=/usr \
    --with-freetype-dir=/usr \
    --with-t1lib=/usr \
    --enable-gd-native-ttf \
    --enable-gd-jis-conv \
    --with-openssl \
    --with-mysql=/usr \
    --with-pdo-mysql=/usr \
    --with-gettext=/usr \
    --with-zlib=/usr \
    --with-bz2=/usr \
    --with-recode=/usr \
    --with-mysqli=/usr/bin/mysql_config \
    --with-apxs2=/usr/bin/apxs2 # これ

かなり長いですが、気長に待ちましょう。
成功すると「Thank you for using PHP.」と出力され、Makefileが生成されます。
エラーが出た場合は頑張ってください。

続いてビルドを行います。

$ make

raspberry pi 3ではCPUが非力なため、1時間かそれ以上というかなりの時間がかかります。
放置して別の作業するなり仮眠するなりすると良いです。

コンパイルが成功するとmake testをするように促されますが、これもまた長いので今回は割愛してそのままインストールします。
本来は行ったほうが良いので、時間が許すのであれば実行しておきましょう。

$ sudo make install
...
libtool: install: install .libs/libphp7.so /usr/lib/apache2/modules/libphp7.so
libtool: install: install .libs/libphp7.lai /usr/lib/apache2/modules/libphp7.la
libtool: install: warning: remember to run `libtool --finish /home/pi/php7/php-7.1.7/libs'
chmod 644 /usr/lib/apache2/modules/libphp7.so
[preparing module `php7' in /etc/apache2/mods-available/php7.load]
...

上記のような出力がされればインストールが完了です。
ログにも書かれていますが、「/etc/apache2/mods-available/php7.load」にモジュールが追加され、条件が合えば自動で有効化されるようです。
現段階では動かないのでとりあえずこれで問題ありません。


Apache 2のMPMをPreforkに変更

Apache 2はデフォルトの場合、MPM eventで動作していますが、この場合PHPは動作しません*訂正
ですので、Preforkに変更する必要があります。(Workerでも動くらしい、未確認)
現在動作しているMPMは「apache2ctl -V」で確認できるため、念のため確認しておきましょう。

$ sudo apache2ctl -V
Server version: Apache/2.4.10 (Raspbian)
Server built:   Jul 18 2017 22:21:17
Server's Module Magic Number: 20120211:37
Server loaded:  APR 1.5.1, APR-UTIL 1.5.4
Compiled using: APR 1.5.1, APR-UTIL 1.5.4
Architecture:   32-bit
Server MPM:     event
  threaded:     no
    forked:     yes (variable process count)
Server compiled with....
...

「Server MPM: event」となっているとeventですので動作しません。

では、本題の切り替えですが、MPMの切り替えは以下の2コマンドで可能です。

$ sudo a2dismod mpm_event # eventの無効化
$ sudo a2enmod mpm_prefork # preforkの有効化

これでpreforkに変更されます。


Apache 2の設定

次にphp7を有効化します。
make install前にpreforkにしていた場合は既に有効化されているかもしれませんが、念のため試しておきましょう。

$ sudo a2enmod php7

ちなみにですが、php5からのアップグレードの場合はa2dismod php5も追加で実行しておいてください。

次に、コンフィグファイルを作成、変更します。
今回は説明を簡易にするためapache2.confを変更しますが、必要に応じて変更箇所を変えてください。別でコンフィグを作ることにしました。

$ cd /etc/apache2/conf-available
$ sudo nano php7.conf
<IfModule php7_module>
        AddType application/x-httpd-php .php
        AddType application/x-httpd-php-source .phps
</IfModule>

$ sudo a2enconf php7
$ sudo apache2ctl restart

エラーがでなければこれで完了です。
あとはphpinfo();で確認して以下のようになっていれば完了です。
f:id:AonaSuzutsuki:20170724002852p:plain


[補足] php.iniの場所

今回は特に変更をかけませんが、補足で独自定義用のphp.iniを作成します。

$ cd ~/tmp/usr/etc
$ echo | sudo tee php.ini

あとはApache 2を再起動すると作成したphp.iniが読み込まれるようになります。


追記

mpm_eventでPHPが動かないのではなく、モジュール版PHPが動作しなくなります。
mpm_eventではスレッドを用いてリクエストの処理をするため、複数のリクエストを処理する場合、メモリ空間上で競合が発生する可能性があり、スレッドセーフなモジュールでなければ動作しないようです。
eventで動作させる方法は無いのではなく、FastCGIを用いて動作させてやれば動くようです。
まだ実際に試していませんが、試したらまた記事かなにかで書きます。


参考とリンク


*1 Requirements, https://wordpress.org/about/requirements/

*2 PHP: Downloads, http://php.net/downloads.php

*3 PHPNG (next generation), https://wiki.php.net/phpng