Ubuntu

WordPress メディアがすべて0バイトに見える

家族専用のブログを別環境に移設したところ、メディアがすべて0バイトに見える。
ディレクトリを丸ごとバックアップしておけば、それをリストアするだけで使えるはずなのに…なんでだろ?



広告


症状

OSはUbuntu 22.04、WebサーバーはApache、DBサーバーはMariaDB、WordPressが動作している環境。

メディアファイルはちゃんと復元できているが、中身が見られない。
メディアのURLに直接アクセスすると、NOT FOUNDにならず、0バイトのファイルに見える。

このように、ひどい有様になっている。

デバッグログをオンにして、関係しそうな箇所でログを出力させたけれど、どうやらメディアファイルの位置を正しく指しているようだった。

原因と対策

WordPress側でX-Sendfileを使ってコンテンツを配信しようとしているのに、ApacheでX-Sendfileの設定をしておらず、ファイルが送信されていなかった。
具体的には、以下の設定をセットで入れるか、セットで外しておかなければならない。

wp-config.php

define( 'WPMU_SENDFILE', true );

/etc/apache2/sites-available/hoge.conf

XSendFile on
XSendFilePath /path/to/wordpress/wp-content/blogs.dir

※古くから使っているのでこんなディレクトリだけれど、新しいセットアップでは、/path/to/wordpress/wp-uploads になる想定。

こうなってしまった経緯は…

ということで、ちぐはぐな状態になってしまった。

なお、ApacheでX-Sendfileを使用する場合には、以下のライブラリをインストールしておく必要があるので、メモしておく。

$ sudo apt install libapache2-mod-xsendfile

やったこと

かなり昔に設置したWordPressで、自動でバージョンアップが繰り返され、現在は6.2.2になっている。

マルチサイト設定がしてあって、コンテンツは wp-contents/blogs.dir に保管されている。
これはかなり昔に変更されていて、今は wp-uploads に保管されるようだ。

最初はこれが原因?と思って色々と調査をしていた。

WordPressのリストア

0バイト問題が全然解決できないので、VMware PlayerにUbuntu 22.04 desktopをインストールして、色々と試せる環境を作ることにした。
雑なメモだけれども、Apacheのモジュール以外はだいたいこれで行ける。モジュールはエラーが出たら追加すればOK。

MariaDBをインストールし、ユーザーを作る。
データーベースはwordpress、ユーザーはwordpressの想定で作成。

$ sudo apt install mariadb-server
$ sudo mariadb
MariaDB [(none)]> create user wordpress;
MariaDB [(none)]> set password for wordpress = password('**masked**');
MariaDB [(none)]> create database wordpress default character set utf8mb4 collate utf8mb4_unicode_520_ci;
MariaDB [(none)]> grant all privileges on wordpress.* to wordpress@'%';
MariaDB [(none)]> quit

※パスワードはマスクしている。

データーベースwordpressの復元。

$ mysql -u wordpress -p -D wordpress < /opt/wordpress/backup/root/work/backup/wordpress.dmp 
Enter password: 
ERROR 1064 (42000) at line 2177: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'Process 76109 detected
Child process is finished, exiting...' at line 1

※エラーは、ダンプに出力処理結果が乗っかっていて、それが文法エラーとして検出されているもの。データーベースはすべて復元できているので無視する。

PHPと、mysqlを操作するためのライブラリをインストール。

$ sudo apt install php php-mysql
$ php --version
PHP 8.1.2-1ubuntu2.11 (cli) (built: Feb 22 2023 22:56:18) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.1.2, Copyright (c) Zend Technologies
    with Zend OPcache v8.1.2-1ubuntu2.11, Copyright (c), by Zend Technologies

Apacheにとりあえず動くサイトを設定。
サーバーはhogeserver.hogeddns.jpにマスクしている。

php_valueは.htaccesにあったものだけれど、エラーになったのでこのファイルに持ってきた。
システム管理メモ / Apache2.4: php_value not allowed here

hoge.conf

<VirtualHost *:80>
    ServerName hogeserver.hogeddns.jp
    RewriteEngine On
    RewriteCond %{HTTPS} off
    RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI}
</VirtualHost>

<VirtualHost *:443>
        ServerName hogeserver.hogeddns.jp
        DocumentRoot /path/to/wordpress

        ErrorLog  ${APACHE_LOG_DIR}/hoge-error.log
        CustomLog ${APACHE_LOG_DIR}/hoge-access.log combined

        SSLEngine on
        SSLCertificateFile      /path/to/crt/hogeserver.hogeddns.jp/fullchain.pem
        SSLCertificateKeyFile   /path/to/key/hogeserver.hogeddns.jp/privkey.pem

#       XSendFile on
#       XSendFilePath /path/to/wordpress/wp-content/blogs.dir

        <Directory /path/to/wordpress>
                Require all granted
                DirectoryIndex index.php
                AllowOverride FileInfo
                FallbackResource /index.php
        </Directory>
</VirtualHost>

本来なら、ココでXSendFileの設定を入れておくべきところであって、これが0バイトの原因。
この機能を使うためにはライブラリをインストールする。

$ sudo apt install libapache2-mod-xsendfile

さて、必要なモジュールを追加して、Apacheを再起動。

$ sudo systemctl restart apache2

ブラウザーからリストアした環境にアクセスするために、以下の設定で自分に向ける。

/etc/hosts

192.168.110.113 hogeserver.hogeddns.jp

※127.0.0.1でもアクセスはできると思うけれど、なんとなく割り付けたローカルのIPアドレスを設定。

これでクローンすることができたが、メディアが見られない。
元々のサーバーでは、/usr/share/wordpressでサービスを構成していたので、一応そこに移して試してみたが、結果は同じでメディアが見られない。

Apacheのログを見る

今回の設定だと、以下にログが出力される。

/var/log/apache2/hoge-access.log

192.168.110.113 - - [08/Jul/2023:18:44:19 +0900] "GET /subsite/files/2020/03/hoge.jpg HTTP/1.1" 200 5025 "https://hogeserver.hogeddns.jp/subsite/" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0"

画像へのアクセスに対して、200 OKが戻されている。

でも、0バイトのファイルだから、何も見えない。

WordPressのデバッグログを見る

デバッグに関して、公式で教えてくれている。
WordPress.org 日本語 / WordPress でのデバッグ

こんな感じで書いておいて、必要になったら、コメント行→有効行に切り替えればいいかなと。

wp-config.php

define( 'WP_DEBUG', true );
if ( WP_DEBUG ) {
    // デバッグログファイルを出力する wp-content/debug.log
    // PHPのビルトイン関数error_log()関数を使うとログを出力できる
    define( 'WP_DEBUG_LOG', true );

    // デバッグログを画面に出力しない
    //define( 'WP_DEBUG_DISPLAY', false );
    //@ini_set( 'display_errors', 0 );

    // CSSやJavaSctiptで開発版を使用(通常は縮小版)
    //define( 'SCRIPT_DEBUG', true );

    // データベースクエリを配列に保存して表示する
    //define( 'SAVEQUERIES', true );
}

今回の場合は、エラーじゃないので、デバッグログは出力されなかった。

ディレクトリ変換の様子を見る

古いセットアップなので、メディアの格納先は wp-contents/blogs.dir となっている。

探してみると、以下のファイルで、ms_files_rewritingというサイトオプションがあれば、ディレクトリを編集しているようだった。
この変換処理で何か起きているの?と思い、ファイルを探してデバッグログを入れてみた。

wp-includes/ms-default-constants.php

...
function ms_upload_constants() {
        // This filter is attached in ms-default-filters.php but that file is not included during SHORTINIT.
...
        }
        error_log("ms_upload_constants " . BLOGUPLOADDIR,0);
}
...

画像にアクセスしたところ、以下のようなログが出力される。

wp-contents/debug.log

[08-Jul-2023 10:09:19 UTC] ms_upload_constants /var/www/html/wp-content/blogs.dir/2/files/

ページのソースを確認すると、この時には以下のURLの画像をとってってこようとしている。

https://hogeserver.hogeddns.jp/subsite/files/2023/02/hoge.jpg

これを連結してみたファイルの存在を確認してみると、ちゃんと存在している。

$ ll wp-content/blogs.dir/2/files/2023/02/hoge.jpg
-rw-r--r-- 1 www-data www-data 17429  2月  4 15:34 wp-content/blogs.dir/2/files/2023/02/hoge.jpg

これは、ディレクトリ変換がちゃんと動いていることを表している。

X-SendFileを設定してみる

ここまできて、確かにApacheのサイト設定が雑すぎるな…と気付き、1行ずつ確認していった。
この設定ができていないな、ということで「本番サイト」の設定をそのままコピー、ディレクトリが違う状態。

hoge.conf

<VirtualHost *:443>
...
        XSendFile on
        XSendFilePath /usr/share/wordpress/wp-content/blogs.dir
...
</VirtualHost>

画像にアクセスしてみたところ、WordPressの404じゃなく、Apacheが404を出している。
じゃあ、存在しないファイルにアクセスしたらどうなる?と確認すると、通常通りWordPressが404を返してくれる(殺風景だけれども昔のテーマだし)。

X-SendFileについては、こちらで説明されている。なるほど!
Nginx / XSendfile
Nginx / X-Accel

これを読んで想像するに、X-SendFileというのは…

  • WordPressは動的にコンテンツを生成する仕組みだけれど、アップロード済みのメディアファイルは静的。
    WordPressとしてはコンテンツ生成で頑張りたいので、静的ファイルの配信はWebサーバーに任せたい。
  • そこで、WordPressはヘッダーにメディアファイルのURLを書いておいて、ボディーからリダイレクトさせるように仕掛ける。
    アクセスしてきたブラウザは、例えば写真を表示しようとしたら、ん?ヘッダーを見ろって?と、ヘッダーのURLを見て、要求。
  • 要求を受けたWebサーバーは、要求をWordPressに渡さずに、自分で静的ファイルを配信する。
    WordPressは動的コンテンツの生成を頑張る

という仕掛けのようだ。
設定ミスによってApacheがファイルにたどり着けなくなったので、自分でエラーを出力するな、と。

X-SendFileの設定していなかったことで、

  • WordPressとしては、静的ファイルの配信をApacheに任せたつもり。
  • Apacheは、X-SendFileを処理するように設定していないから、何もしない(というか、0バイトのファイルを返している?)。
  • ブラウザには何も表示されない。

ということになっていたのだった。

間違ったApacheの設定を直して、この問題は収束した。

さいごに

とにかく時間が掛かった。

手を抜く場所を間違った結果、最後までその手抜きにやられている、という感じ。
急がば回れというヤツだ。

1つ1つ丁寧に進めると、最終的には早く結果が得られる。

まぁ、おかげで幾つかの学習ができたのだから、良しとするか。

広告

コメントはこちらから お気軽にどうぞ ~ 投稿に関するご意見・感想・他