ZTS 版の PHP に PECL 拡張モジュールをインストールする
PHP に PECL 拡張モジュールをインストールしようとしてハマったのでメモ。
PHP で ImageMagick を使うためのラッパーであるimagick(pecl.php.net)のインストールを例にします。
pecl install
でインストール
まずは普通にインストールしてみます。 ImageMagick については、 yum install ImageMagick
だと古いバージョン6系がインストールされてしまうので、公式サイトのダウンロードページ(imagemagick.org)から7系最新バージョンの RPM ファイルを直接指定してインストール。
yum install https://imagemagick.org/download/linux/CentOS/x86_64/ImageMagick-libs-7.0.10-29.x86_64.rpm
yum install https://imagemagick.org/download/linux/CentOS/x86_64/ImageMagick-7.0.10-29.x86_64.rpm
yum install https://imagemagick.org/download/linux/CentOS/x86_64/ImageMagick-devel-7.0.10-29.x86_64.rpm
続いて PECL で imagick をインストールします。
- これは ZTS 版の PHP ではダメな例であり、後でアンインストールする羽目になります。失敗の経験も含めて書き残しておく次第です。
pecl install imagick
インストールが完了するとこうなります。
Build process completed successfully
Installing '/usr/lib64/php/modules/imagick.so'
Installing '/usr/include/php/ext/imagick/php_imagick_shared.h'
install ok: channel://pecl.php.net/imagick-3.4.4
configuration option "php_ini" is not set to php.ini location
You should add "extension=imagick.so" to php.ini
このメッセージでとくに重要なのは以下の2点です。
- モジュールディレクトリ(/usr/lib64/php/modules/)に imagick.so がインストールされた
- php.ini に "extension=imagick.so" の記述を手動で追加せよ
メッセージどおり php.ini に追記してもいいのですが、他のモジュールと同じように個別の .ini ファイルを作って .so を読み込むようにします。
vi /etc/php.d/20-imagick.ini
ファイルの中身はこれだけ。
extension=imagick
-
インストールのメッセージでは前述のとおり "extension=imagick.so" と書くように指示されていますが、これは古い書き方です。公式マニュアルには
PHP 7.2.0 以降では、拡張機能の名前が、拡張機能のファイル名の代わりに使えるようになりました。 これは OS に依存せず、特に初心者に簡単な仕組みです。 これは、読み込む拡張機能を指定する推奨できるやり方になっています。
(www.php.net)とあるので、拡張子なしの記述の方が良いでしょう。こうすることで開発機は Windows 、本番環境は Linux といった場合でも記述を統一できるメリットがあります。
php -m
してみると、ちゃんと imagick も追加されています。
Web 画面の phpinfo() で認識されない
ところが、 Web 画面で phpinfo() を見ると imagick は追加されていません。よく見ると「Scan this dir for additional .ini files」のディレクトリが「/etc/php-zts.d」となっています。また extension_dir も「/usr/lib64/php-zts/modules」です。
この zts とは何なのかいろいろ調べてみたところ、以前サイトを HTTP/2 対応した際、 Apache の動作を prefork → event に変更したことが原因だと分かりました。 Apache + PHP の組み合わせでは、 Apache が prefork モードでない場合、 Zend Thread Safety(ZTS)版の PHP が読み込まれるようになるようです。これは Apache の設定ファイル(私の環境だと /etc/httpd/conf.modules.d/15-php.conf )に書かれています。
#
# PHP is an HTML-embedded scripting language which attempts to make it
# easy for developers to write dynamically generated webpages.
#
# Cannot load both php5 and php7 modules
<IfModule !mod_php5.c>
<IfModule prefork.c>
LoadModule php7_module modules/libphp7.so
</IfModule>
</IfModule>
<IfModule !mod_php5.c>
<IfModule !prefork.c>
LoadModule php7_module modules/libphp7-zts.so
</IfModule>
</IfModule>
つまり、先ほど実施した pecl install
では非 ZTS 版の方にインストールされてしまったので、 php コマンドを叩くと認識されるものの、 Web の PHP にはインストールされていないということだったのです。 ZTS 版の PHP の実態は /usr/bin/zts-php にあるので、 php -m
でなく zts-php -m
をすると、やはり imagick は追加されていませんでした。
ZTS 版の PHP に PECL 拡張モジュールをインストール
で本題ですが、 pecl install
に ZTS 版へインストールするオプションがあれば一発解決なのですが、どうやらそのようなものはなさそうです(この辺あまり詳しくないので、もしあったら教えてください)。
なので手動ビルドすることにします。 PECL のimagick のページ(pecl.php.net)へ行き、最新バージョン(2020年9月9日現在は 3.4.4)の URL を調べて落とします。
wget https://pecl.php.net/get/imagick-3.4.4.tgz
gunzip imagick-3.4.4.tgz
tar -xvf imagick-3.4.4.tar
あとは公式マニュアルのphpize で共有 PECL 拡張モジュールをコンパイルする方法(www.php.net)を参考にしますが、下記2点に注意です。
- phpize の代わりに zts-phpize を使う
- ./configure のオプションで ZTS 版の php-config を指定する
cd imagick-3.4.4
zts-phpize
./configure --with-php-config=/usr/bin/zts-php-config
make
sudo make install
あとは先ほどと同じ要領で設定ファイルに "extension=imagick" を記述します。
vi /etc/php-zts.d/20-imagick.ini
サーバーを再起動すると、 Web 版の phpinfo() にも imagick が追加されました。
最後に、非 ZTS 環境にインストールしてしまった imagick をアンインストールします。
pecl uninstall imagick
rm /etc/php.d/20-imagick.ini