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

サムネイル画像
pecl install imagick が終わった時のコンソール画面オリジナル画像

このメッセージでとくに重要なのは以下の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

php -m してみると、ちゃんと imagick も追加されています。

サムネイル画像
php -m した結果オリジナル画像

Web 画面の phpinfo() で認識されない

§

ところが、 Web 画面で phpinfo() を見ると imagick は追加されていません。よく見るとScan this dir for additional .ini filesのディレクトリが /etc/php-zts.d となっています。また extension_dir/usr/lib64/php-zts/modules です。

サムネイル画像
phpinfo() 画面の最上部のシステム情報部分オリジナル画像

この zts とは何なのかいろいろ調べてみたところ、以前サイトを HTTP/2 対応した際、 Apache の動作を preforkevent に変更したことが原因だと分かりました。 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 が追加されました。

サムネイル画像
phpinfo() 画面の imagick 部分オリジナル画像

最後に、非 ZTS 環境にインストールしてしまった imagick をアンインストールします。

pecl uninstall imagick

rm /etc/php.d/20-imagick.ini