CentOS7でPHP8.2.35をコンパイルして使う

掲載日

CVE-2026-109618、 CVE-2026-109619では、パッチが配布されたのはPHP7.4以降になります。
比較的新しいOSやサポートの長い(redhatなら5年?)OSを使用していて、かつPHP8.2以上を使用していれば以下で対応は終わったと思います。バージョン同じなのでソフトに影響出る人もほぼほぼいないと思います。

dnf update php

よしんばPHPのバージョンが古くても、以下のコマンドでPHPのバージョンアップ自体はサクッと行けると思います。(※バージョン代わるとソフトにはがっつり影響出るので注意。)

dnf install epel-release

dnf module reset php
dnf module enable php:remi-8.4 # ここは入れたいPHPのバージョンに合わせる
dnf distro-sync php

PHPがちょっと古く(PHP8.1以前)、Cent OS8とか9くらいになるとちょっと怪しくてミラーサーバーのURL書き換えたりしましたがまだPHP本体の更新をdnfコマンドで行けるのでマシです。

# URL書き換え
sed -i 's/^mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-*
sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-*

# 後は上と同じコマンドで大体いけると思う。

問題はCent OS7で、これはリポジトリが止まっているのでもうミラーサーバーのURL書き換えたってどうにもならない。

dnfコマンドで良い感じにアップデートはできないので、php公式で配布しているソースコードをコンパイルして使用していきます。

 

コンパイル環境と前提

  • Cent OS 7
  • PHP7.4 から PHP8.2 に変更(PHP7.4はパッチ配布対象なので上げなくても良かったかも。tarが公式で配られているから8.2にしてますが、7.4も多分gitからインストールして来てやることは同じだと思います。)
  • PHPで動かすソフトは気合でインストールするPHPバージョンに対応させていること
  • OS7の中でも細かいバージョンの差分や、依存するライブラリの細かいバージョンの違いがあり、
    必ずこの手順で上手く行くわけではないことをよくご認識頂き、一旦仮想マシンで試してください。
    (実機でいきなり実行はNG。何かあっても責任は負いかねます。)

手順

ソースコードダウンロード

まずphpの公式からソースコードをダウンロードします。
リンクにアクセスして、「Old Stable PHP 8.2.35」の「php-8.2.35.tar.gz」と書いてあるリンクをクリックしてください。
(圧縮形式は自分のサーバー環境で解凍できればどれでもいいです。)

ダウンロードしたファイルはSCPなりrsyncなりWinSCPなりでサーバーの作業用ディレクトリに配置します。
ここでは仮に/tmpに配置します。
(サーバーによっては/tmp配下は自動でクリーンしてたりすると思うので、実際の作業ではどこかオープンでない場所に作業用ディレクトリ作ってやることを推奨します。)

とりあえずconfigure

まず間違いなく成功しませんが、とりあえず配置したディレクトリに移動して、configureを実行します。

なお、以下は恐らく必要な最小のオプションを付けていますが、実際は現在動いているphp.iniの設定などからextensionsを確認して、必要な拡張機能を追加する必要があります。

例えば、以下の場合使わないことはほぼないだろうという事でmbstringをONにするためにenable-mbstringを付けています。
(自分の実際の環境の場合、更にPostgresqlを使うために--with-pgsql=/usr/pgsql-XXや--with-pdo-pgsql=/usr/pgsql-XXオプションを追加する等しました。
どのextensionsにどのオプションが必要か都度調査する必要があるため、巨大なソフトであればあるほど移行の手間がかかると思います。)

cd /tmp/php-8.2.35/
./configure \
--prefix=/usr/local/php82 \
--with-apxs2=/usr/bin/apxs \
--with-config-file-path=/etc \
--enable-mbstring

パッケージが無いというエラーが出るため、都度 yum install 

上記コマンドを実行すると、「○○というパッケージが無いよ」というエラーが表示されますので、
都度パッケージと、そのパッケージ名の後ろに「-devel」を付けたパッケージをインストールしてください。

エラーメッセージだけだとそのパッケージがあればいいような気がしますが、コンパイルするために開発用のパッケージが必要になるため「-devel」付が必要になります。

例えば自分の場合、postgresql12のパッケージは元から入っていましたが、postgresql12-develのパッケージも必要になるため以下のコマンドを実行しました。

yum install postgresql12 postgresql12-devel

もうないパッケージを探しに行く

パッケージを入れる→configure実行するの繰り返しで最後までエラー無で通ればいいですが、パッケージが見つからないケースがあります。

自分の場合、postgresql12を使っており、使っているので実行用パッケージは入っていたのですが、postgresql12-develがないため、滅茶苦茶ググり回り、以下のサイトにて見つけました。

  • RPM RedHat EL 7 postgresql12-devel 12.20 x86_64 rpm
    以下をよく確認してください。
    • ELの後ろの数字が自分のOSのバージョンと合っていること
    • パッケージのバージョンがあっていること
      (自分の例で言うと、postgresql13がサーバーでは動いているのに上記を入れることは試しては無いですが出来ないと思います。)

 

ダウンロードが出来たら、これも作業用ディレクトリ(今回の自分の例であれば/tmp)に配置して、
yum install /tmp/postgresqlXX-devel-XX-1PGDG.rhelXX.x86_64.rpmを実行します。
(postgresqlXX-devel-XX-1PGDG.rhelXX.x86_64.rpm部分は各自の環境に合わせて変更。)

これでエラーが出なければパッケージインストールが出来ているので、またconfigure実行に戻りましょう。

configureが通ってmakeでエラー

configureが通ったらあと少しです。続いて、makeコマンドを同じディレクトリ内で実行します。
すんなり通ればOKですが、エラーが出て来ることがあります。
エラーメッセージを見て、cスクリプトを修正と再実行を繰り返します。

自分の場合、/tmp/php-8.2.35/ext/openssl/xp_ssl.cというスクリプトの以下の点を修正しました。

// 修正前のコード
ASN1_STRING_get0_data(san->d.iPAddress)[0]
// 修正後のコード
ASN1_STRING_data(san->d.iPAddress)[0]

// 変更前(524行目付近)
    EXPAND_IPV6_ADDRESS(ipbuffer, ASN1_STRING_get0_data(san->d.iPAddress));
// 変更後(行頭に // を付与してコメントアウト)
//  EXPAND_IPV6_ADDRESS(ipbuffer, ASN1_STRING_get0_data(san->d.iPAddress));

これでmakeが通ればOK。途中WARNINGが出ますがそれは無視します。

make installが通ったら実行ファイルを差し替える

上記makeが通ったらmake installを実行します。
ここでもエラーが出なければ、configureを実行した際にオプションで付けた--prefix=/usr/local/php82のパスにphpの実行ファイルが生成されているハズです。

まずは、実行できるかと目的のバージョンになっているかを確かめます。

 /usr/local/php82/bin/php -v
 # => バージョンが表示されるので、パッチ適用バージョンになっているか確かめること。
 # PHP8.2の場合、PHP 8.2.35以上

問題が無ければ、which phpを実行して出てきたパスと、今回作成したパスを入れ替えます。

# which phpの結果が/usr/bin/phpだと仮定して、以下のようにします。
mv /usr/bin/php{,.bk}
ln -s /usr/local/php82/bin/php /usr/bin/php

オプション設定等によっては、/usr/local/php82/lib/php/extensions/no-debug-non-zts-XXXXX/配下に.soファイルが作成されているので、php.iniで適切に読み込みます。

httpdの設定ファイル等も修正の上、サービスを再起動してください。

systemctl restart httpd.service
(ここはnginx等環境に合わせて変える必要があります。)

これで動けば今回の延命は成功です。
ただ、延命は延命です。なるべく早めにOSのバージョンやPHPのバージョンを上げる方向に動きましょう。

おわりに

ここまでの手順で駄目でも他の方法はあるかもしれません。
ただ、これ以上頑張れない場合、以下の負債を返してなんとか公開までこぎつけるか、すっぱり諦めてサービス終了とかになると思います。

  • OSを最新にする
  • PHPもバージョンを最低限パッチ配信版(PHP7.4)まで上げる
  • 自社サービスを最新版PHPに対応させる
    (使ってるライブラリが古くて更新もしておらず、代替ライブラリも無さそうな場合更なる地獄が待ち受けています。vendorの中身を直接修正してサーバーにアップロードする力技でも行けなくはないですが、ライブラリの規模や依存度、修正範囲と内容によっては…。)

 

PHP以外にも言えることですが、OSも言語もバージョンもこまめに上げられるなら上げないといけない時代になってしまったのかもしれません。しかし、PHPだけならともかく、OSバージョンの場合サーバーも新しくする必要があると思うので、そこそこの費用が必須になるのがなんとも悩ましいです。

    • BlueSkyで共有する
    • Hatenaで共有する
記事の作成者のW.Aのアイコン

この記事を書いた人

W.A
茨城県在住Webエンジニアです。 PHP、PostgreSQL、Linuxなどを業務で使用しています。 趣味ではGoやNuxt、Flutterをやってます。
  • GitHubのリンク

Comment

関連記事

  • 絵文字のアクセシビリティのサムネイル画像

    絵文字のアクセシビリティ

    掲載

    生成AIの登場で絵文字がふんだんにあしらわれた記事を見かけることが増えました。絵文字はスクリーンリーダーではどのように読み上げられ、どのようなアクセシビリティ対策が出来るのか、また推奨されているのか調査し、PHPを使ってaria-hiddenでマークアップする方法をまとめました。

  • PHP cURLのデフォルトタイムアウトは0(無制限)のサムネイル画像

    PHP cURLのデフォルトタイムアウトは0(無制限)

    掲載

    PHPのcURL処理では、デフォルトではタイムアウトの設定が0(無制限)となっており、転送中はタイムアウトしません。実行したAPIの不具合やネットワークの不調等でプロセスが残り続けて思わぬ障害を発生させるため、タイムアウト設定とその確認方法の備忘録。

  • PHPで見た目が同じ違う漢字に立ち向かうのサムネイル画像

    PHPで見た目が同じ違う漢字に立ち向かう

    掲載

    見た目は同じなのにDBやCtrl+Fでの文字列検索にヒットしない文字がある原因は「CJK部首補助」等の特殊な文字コードの混入かもしれません。PDFコピペ等で発生するこういったトラブルを、PHPでの自前マッピングで解決した備忘録です。

check コピーしました!