KUSANAGI 8でPHP8.0が使えるようになりました。さっそくPHPのバージョンを上げたんですが、テーマやプラグインのアップデートで Internal Server Errorが出る。
Webサーバーのログを見ると、PHPにエラー発生。致命的です。
KUSANAGIの最新バージョンの KUSANAGI 9 はすでにPHP8が使えるようになってたんですが、1世代前の KUSANAGI 8 でもPHP8が使えるようになりました。
PHP7.4のサービス終了が目前に迫ったこと(2022年11月)による対応だそうです。
そこでリリース後すぐにPHP8に変更したんですが、致命的なエラーが出ました。内容をくわしく見ていきましょう。
WordPress | 5.9.3 |
PHP | 8.0.18 |
KUSANAGI | 8.6.8-2 |
エラーの原因はWordPress本体の管理用ソース
まずはエラーの内容から。Webサーバー(nginx)のエラーログに出てました。
2022/05/07 18:29:52 [error] 123601#0: *409332 FastCGI sent in stderr: "PHP message: PHP Fatal error: Uncaught Error: socket_close(): Argument #1 ($socket) has already been closed in /home/user/www/DocumentRoot/wp-admin/includes/class-ftp-sockets.php:233
Stack trace:
#0 /home/user/www/DocumentRoot/wp-admin/includes/class-ftp-sockets.php(233): socket_close(Object(Socket))
#1 /home/user/www/DocumentRoot/wp-admin/includes/class-ftp.php(867): ftp_sockets->_data_close()
#2 /home/user/www/DocumentRoot/wp-admin/includes/class-ftp.php(508): ftp_base->_list(' /home/user...', 'NLST', 'nlist')
#3 /home/user/www/DocumentRoot/wp-admin/includes/class-wp-filesystem-ftpsockets.php(422): ftp_base->nlist('/home/user/...')
#4 /home/user/www/DocumentRoot/wp-admin/includes/class-wp-filesystem-base.php(229): WP_Filesystem_ftpsockets->exists('/home/user/...')
#5 /home/user/www/DocumentRoot/wp-admin/includes/class-wp-filesystem-base.php(76): WP_Filesystem_Base->find_folder('/home/user/...')
#6 /home/user/www/DocumentRoot/wp-admin/inclu"
Uncaught Error は例外が発生したのに一度も例外をキャッチしなかったときに出ます。そして例外が発生した理由は、クローズしたソケットでまたクローズしようとしているというもの。
ソースコードはこちら。
function _data_close() {
@socket_close($this->_ftp_temp_sock);
@socket_close($this->_ftp_data_sock); // <--- add comment: ここで発生。
$this->SendMSG("Disconnected data from remote host");
return TRUE;
}
そこでボクが対応した修正はこちら。
function _data_close() {
@socket_close($this->_ftp_temp_sock);
try {
@socket_close($this->_ftp_data_sock);
} catch ( Error $e ) {
}
$this->SendMSG("Disconnected data from remote host");
return TRUE;
}
FTPソケットのクローズをするタイミングは、通信が終了して処理が終わるころです。
失敗したところで、ソケットディスクリプタ(socket_close()の引数値)をそれ以降に使うことはないので、例外をキャッチしてそのまま処理を続行しています。
本来、WordPressのソースは編集しないんですが(WP更新で修正が消えるので。)、このタイミングでのエラーは原因特定が難しいと瞬間的に思ったので入れました。
(後ろで追記しているが、修正の必要はなくwp-config.phpの設定変更で対応可能。)
PHP8はエラーレベルがWarningからErrorに上げられている。
PHPは7から8にメジャーアップデートされて変わったことのひとつに、エラーレベルの見直しがあります。
おもに、警告だったものがエラーになりました。
Uncaught Error もPHP7以前は警告止まりだったんですがPHP8以降はエラーです。
PHP8では発生した例外を必ず一度はキャッチしないとエラーになるほど、いろんなところで厳密化されています。
KUSANAGIが原因とは思えないんだけど。
WordPressでの不具合は、拡張部分、テーマやプラグイン、ドロップイン(組み込みの拡張機能)が大半ですが、ソケット通信のエラーとなるとちょっとちがいます。
調べてて分かったことだけを列挙します。
KUSANAGI 9 では起きない
なぜか、KUSANAGI 9 では起きません。VirtualBox のイメージから環境を作って確認しました。
それならKUSANAGI 8 で何かしら原因になってるのか? と思いがちですが、処理の内容からしてその可能性は低いと考えられます。
エラーが発生したのはソケット通信の部分。普通、テーマやプラグイン、KUSANAGIのようなドロップイン(組み込みの拡張機能)はその処理に影響があるとは思えません。
答えは最後の『追記』にあるんですが、wp-config.phpの設定のちがいでした。
同じエラーが出たという情報が見当たらない
この大事なところで出るエラーだったら、WordPressを使ってる人だったり、KUSANAGIを使ってる人だったり、いろんな方面から情報が出てくると思います。
ただこの情報はなかなか見当たらない。
KUSANAGI, WordPress, テーマ, プラグインの全体的な相性が悪い?
WordPressでは、エラーの場所が分かっても原因が分からないことがあります。テーマやプラグインなどが原因で、関係なさそうなところでエラーが出たりするから。
ソケットのクローズで失敗とか普通考えられません。頻繁に処理が行われるところで、かなりブラッシュアップされてプログラムの完成度は高いはずだから。
サイト表示に問題はない。影響あるのはアップデートだけ。
このエラーはwp-admin内で起きていて管理画面での話なので、サイト表示には影響ありません。
管理画面でもソケット通信を使うところだけなので、影響するのはテーマ・プラグインのアップデートくらいです。
追記。ちゃんとKUSANAGIのFAQに解決方法があるじゃん。
実はこのエラー、1ヶ月前くらい(2022年4月末)から知っていました。エラー内容からしてどこが原因なのか分からないから、ソースコードを修正して放置していた。
それで、これを書いて最後にもう一度、情報がないか確認したところ、思いっきりKUSANAGIのサイトのFAQにあります。
wp_config.phpの設定を変えるだけでOK。
define('FS_METHOD', 'ftpsockets');
define('FS_METHOD', 'ftpext');
KUSANAGI 9 については FAQ のいの一番にありました。どこを見ていたんだろう、今までのボクは。
KUSANAGI 9 で起きなくて KUSANAGI 8 で起きた理由もここ。9 は 'ftpext'、8 は 'ftpsockets' の設定になってた。
FS_METHODの内容を確認するために WordPressの情報を探してみると、アップデートの FTPやSSHではうまくいかないことがあるらしい。
FTPやSSHは、OSの通信設定にかなり依存するからでしょう。
wp_config.php の設定はそのためにもあると説明されてる。
ただし、FTP通信の設定は、『アップグレードの問題解決に必要な最低限の定数のみを定義してください。』とあります。
くわしくはこちらをどうぞ。
WordPress.org日本版
やたらめったらいじるなよ、ということらしい。今まで問題が起きてなかったので、この解決方法を見つけるのに時間がかかった。
というか、この問題、やっぱりKUSANAGIは関係ない気がする。
それならもっと情報が出てきてほしいな。
あれか? SEO的なもので、いい情報が検索サイトで上位に表示されない弊害というやつ。
ftpext はパスワード不一致エラーになる。
ボクの環境では、これですべて解決したわけじゃありません。アップデートでFTPS(SSL)を使うと、パスワードは合っているのに不一致のエラーになります。
それも解決しようと思ったんですが、その内容はファイルやディレクトリのパーミッションや所有者を変更するとか、vsftpd の設定を変えるとか。
WordPressやKUSANAGIとは関係ないところなので、ちょっとやりたくないなというものばかり。
(英語サイトが多い。)
なので、やめました。FTPかSSH2 を選べばできるし。
wp-config.phpはOSの設定に影響されやすい
wp-config.phpのFTPの設定の結果はOSのFTP関連の環境に影響されます。
(使ってるFTPサーバーやSSHのソフトウェア、PHPの拡張モジュールとその設定状況による。)
KUSANAGI環境のphp.iniを見てると、openssl, ftp, sshなどは拡張モジュールを使ってません。そのあたりが関係してるんじゃないかな?
またKUSANAGIのPHPは、kusanagi-php7.noarch, kusanagi-php8.x86_64のパッケージで独自に配布されているので、PHP7と8でFTPSの内容がちがうのかもしれない。
PHP7ではFTPSが使えるので。
PHP8はセキュリティが厳しくなったと思って、納得することにしている。
(本当にそうなのかは不明だが。)