LinuxサーバーにPHP5をインストールし、設定を終えてApacheを再起動しようとしたところ、以下のような致命的なエラー(crit)が発生して起動に失敗してしまいました。
# /etc/rc.d/init.d/apache2 restart
Apache2 HTTP Serverを停止中: [ 失敗 ]
Apache2 HTTP Serverを起動中: [Tue Sep 11 00:30:21 2012] [crit] Apache is running a threaded MPM, but your PHP Module is not compiled to be threadsafe. You need to recompile PHP.
Pre-configuration failed「PHPを再コンパイル(recompile)しろって言われてる…?」と焦りましたが、原因と簡単な解決策があったので備忘録として残しておきます。
原因:Apacheの動作モード(MPM)の不一致
エラーメッセージをそのまま直訳すると、「Apacheはスレッド型のMPMで動いているのに、あなたのPHPモジュールはスレッドセーフとしてコンパイルされていません」という意味になります。
実は、PHPインストールの際のログをよく見返してみると、しっかりと警告メッセージが出力されていました(完全にスルーしていました…orz)。
Apache2 is configured to use worker MPM. But php5-apache2 requires prefork MPM. Run the following command as root to switch MPM:
/sbin/update-alternatives --config apache2
つまり、「現在のApacheは『workerモード』で動いているけれど、インストールしたPHPは『preforkモード』じゃないと動かないよ」というのが原因です。
解決策:Apacheを「prefork」に切り替える
警告メッセージの案内に従い、ApacheのMPM(マルチプロセッシングモジュール)を worker から prefork に切り替えます。
root権限で以下のコマンドを実行してください。
# /sbin/update-alternatives --config apache2すると、以下のように選択肢が表示されます。
2 プログラムがあり 'apache2' を提供します。
選択 コマンド
-----------------------------------------------
+ 1 /usr/sbin/apache2.worker
* 2 /usr/sbin/apache2.prefork
Enter を押して現在の選択 [+] を保持するか、選択番号を入力します:ここで 2 (prefork)を入力してEnterを押します。 設定を変更した後、再度Apacheを起動します。
# /etc/rc.d/init.d/apache2 restart
Apache2 HTTP Serverを停止中: [ 失敗 ]
Apache2 HTTP Serverを起動中: [ OK ]無事に起動(OK)しました! (※停止が[失敗]になっているのは、そもそも先ほどのエラーで起動していなかったためです)
補足:prefork と worker の違いとは?
ざっくりとした解説ですが、Apacheの挙動には以下の違いがあります。
- prefork(古くからの標準):リクエストごとに「プロセス」をコピーして処理する。安定性が高いが、メモリ消費がやや多い。
- worker(Apache2からの機能):リクエストを「スレッド」で処理する。メモリ消費が少なくパフォーマンスが良い。
workerの方がパフォーマンスは高いのですが、標準的なPHPモジュール(mod_php)は「スレッドセーフ(複数のスレッドから同時に呼ばれても安全な設計)」になっていないため、安全なpreforkモードで動かすのが一般的なセオリーとなっています。
もしどうしてもworkerモードでPHPを動かしたい場合は、PHPをスレッドセーフ版として自力でリビルド(再コンパイル)するか、FastCGIなどを利用してApacheとPHPを切り離すといった少し面倒な手順が必要になります。
個人レベルのサーバーや、とてつもないアクセスを捌く環境でなければ、手軽な prefork への切り替えで全く問題ありません。 同じエラーで躓いた方の参考になれば幸いです。