WordPress 6.8では、このms-files.phpにバグ報告に上がっていたのがきっかけで、古いマルチサイトの構成から、現在の構成に修正するための手順をまとめました。
古いマルチサイトのフォルダ構成
WordPressマルチサイトを長く運用していると、「メディアにアップロードしたファイルURLが古い形式のまま」「/blogs.dir/
がURLに残っていて直らない」「メディアのファイルURLにfiles
が入っている」という問題に遭遇することがあります。
これは古いバージョンで作られたマルチサイトに多く見られる現象で、現在は使われていません。
古いバージョンのままの場合、サーバ設定でms-files.phpを通すことになります。
WordPress 6.8では、このms-files.phpにバグ報告に上がっており、画像が表示されない不具合が起きています。
実際に表示されるエラー
ms-files.php on line 23 php fatal error: uncaught error: call to undefined function is_super_admin() in ms-files.php:23
Call to undefined function is_super_admin() in /wp-includes/ms-files.php
今回、私のサイトでも実際に発生し、現在は使われていないので、ms-files.phpを介さない現在のやり方に合わせるのことにしました。
かなり手間取ったので、解決までの流れと方法をまとめておきます。
これから同じ状況になる方の参考になれば嬉しいです。
発生していた問題
サーバーに3つのWordPressマルチサイトを稼働させていました。
- 新しい2つのサイトは問題なし。
- 一番古いサイトだけが異常。
この古いマルチサイトで、メディアの「添付ファイルの詳細」からコピペできるファイルURLが、古い形式のURL(例:/files/
が含まれるURL)になっていました。
古い形式のマルチサイトは、メディアのアップロード先がblogs.dir
に保存されます。そして、ms-files.phpを経由して、files
が含まれるURLになります。
今回、ms-files.phpにバグがあり、画像が表示されない現象が起こるというわけです。
ローカルで検証する環境を整える
まずは本番環境をローカルに入れて、データベース内を検証することにしました。
cd /var/www/html/your-wordpress-dir
ドメイン直下に行き、WordPressのデータベース丸々WP-CLIでバックアップします。
wp db export backup.sql --allow-root
次に、ローカルにインポートするためのデータ(本番データの wp_users
・wp_usermeta
を除いてエクスポート)もバックアップしておきます。
wp db export --exclude-tables=wp_users,wp_usermeta
マルチサイトの場合は以下のように --network
をつけて全体を対象にするか、個別に必要なテーブルを指定します:
wp db export --exclude-tables=wp_users,wp_usermeta --url=example.com --allow-root
ローカル環境はLocalを使用しているので、Localが用意しているシェルを使用します。
本番データの wp_users
・wp_usermeta
を除いてエクスポートしたデータをインポートします。このとき、wp_users
/ wp_usermeta
はローカルにそのまま残るので、ログイン情報は変わりません
wp db import filtered.sql
Localにはアプリ上から、データベースを管理できるAdminerとWP-CLIが使用できるシェルコマンドがあります。
Adminerでデータベース内を検証します。
もし本番環境をクリーンしたデータベースに入れ替えたいのなら、下記のコマンドでデータベースがリセットされます。
wp db reset --allow-root
削ぎ落としたデータに入れ替えたいのなら、下記のコマンド。
wp db import local-cleaned.sql --allow-root
初期対応:データベースのURL先を修正する
まず「/blogs.dir/
」の問題を修正して解決しようと考え、次の作業をしました。
メディア→添付ファイルの詳細→ファイルのURLの「https://example.com/files/2024/10/no-images.jpg」と表示されている部分を「https://example.com/wp-content/uploads/sites/21/2024/10/no-images.jpg」に修正します。
修正に当たって、「/blogs.dir/
」内にある画像は全て「/wp-content/uploads/sites/サイトID/」のフォルダ構成に修正します。
URLの置換に当たっては、念には念を入れてWP-CLIでやる方法とSearch Regexというプラグインで置換する方法の2通りで実行します。
【WP-CLI】データベース内を検索して置換
sudo /usr/local/bin/wp search-replace '/files/' '/wp-content/uploads/sites/サイトID/' --url=your-site.com --allow-root --dry-run
--dry-run
は試し実行(実際には書き換えない)なので、置換内容に問題がなければ、--dry-run
を外して本番実行してください。※your-site.comはマルチサイトのサブドメインを指定します。
【Search Regex 】を使った /files/
URL の置換
以下のような画像URLを一括置換したい場合:
https://example.com/files/2025/04/sample.jpg
↓
https://example.com/wp-content/uploads/sites/1/2025/04/sample.jpg
Search Regex を有効化したら、管理画面 → [ツール] → [Search Regex]に推移して、「検索」フィールドに下記を入力します。
/files/
「置換」フィールドに下記を入力して「検索のみ」実行します。
/wp-content/uploads/sites/1/
※ sites/1
の 1
は、そのサブサイトの blog_id に置き換えてください。
内容を確認して問題なければ「置換実行」します。
全てURLは置換したはずなのに?
上記のURLを修正したにもかかわらず、「メディア」「ライブラリ」「添付ファイルの詳細」で「ファイルのURL」を見ると、URLに/files/
が…?URLは直したのに、ファイルのURLが強制的に書き換わっていることを考えると、別の要因が必ずあるはずと考えました。
blogs.dirフォルダの削除 → 復活?
物理的にサーバー上のblogs.dir
フォルダも削除しました。
しかし、削除しても時間が経つとゾンビのように復活する現象が発生…。
この時点で、「これは単なるファイルやパスの問題じゃないな」と直感しました。
次の対応:サーバー設定で応急処置
応急処置として、サーバーの設定ファイル(nginxのconf.d
)に、リダイレクト or リライトルールを追加して、/files/
に来たリクエストを正しい場所へ誘導しました。おそらく、ドメインごとに設定ファイルがあるので、適切場場所に記載してください。
server {
listen 80;
server_name subdomain.example.com;
root /var/www/vhosts/example.com;
# 画像など静的ファイルのリライトルール
location ~ ^/files/(.*)$ {
alias /var/www/vhosts/example.com/wp-content/uploads/sites/サイトID/$1;
access_log off;
log_not_found off;
expires 30d;
}
# 以下、既存のPHPやWordPress関連のlocation等が続く...
}
書き終えたらsudo systemctl restart nginx
です。
リダイレクションなどのプラグインを使う方法もありますが、上記の方法が一番負荷が低いです。
方法 | 特徴 | サーバー負荷 | URL変更 | 推奨 |
---|---|---|---|---|
nginx alias(内部リライト) | 表示URLは変えず、ファイルを読み替え | 低 | なし(静的対応) | 推奨 |
nginx 301リダイレクト | URLごと変更、SEOに最適 | 中 | あり | 状況次第 |
functions.php template_redirect など | 動的対応可能 | 高(PHPが走る) | 任意 | 避けたい |
これで一時的には画像表示できるようになりましたが、根本的な解決ではありません。
本格調査:原因特定
.htaccess
または nginx.conf
に /files/
のリライトルールがあるか?
/files/
を /wp-content/uploads/...
にリダイレクトするような設定が残っていると、見た目だけ /files/
に見えることもあります。
Apache の場合:
.htaccess
の中にこんなルールがないか確認:
RewriteRule ^files/(.+) wp-content/blogs.dir/%d/files/$1 [L]
Nginx の場合:
古いマルチサイトでは、ms-files.php
を介して /files/
のルートパスにリライトルールが書かれています。
/etc/nginx/sites-available/
または /usr/local/nginx/conf/
などに以下のような記述があると影響します。
rewrite ^/files/(.*)$ /wp-content/uploads/$1 last;
私が使用しているサーバ環境の場合は、/etc/nginx/
のwp-multisite-subdir
に下記のソースがあります。ただ、この記載があっても、他のマルチサイトには影響していないので、下記のソースは問題ないと判断しました。
if ($uri !~ wp-content/plugins) {
rewrite /files/(.+)$ /wp-includes/ms-files.php?file=$1 last;
}
マルチサイトの古い設定(blogs.dir
)が残っていないか?
昔の WordPress マルチサイトでは wp-content/blogs.dir/ブログID/files/
という構成でした。この名残りがあると、WordPress が /files/
を生成してしまう場合があります。
確認コマンド:
sudo find wp-content -name blogs.dir
キャッシュの影響
管理画面にキャッシュプラグイン(LiteSpeed Cache や W3TCなど)がある場合、古い値を出している可能性があります。
キャッシュを全部クリアした上で再確認してください。
wp_get_attachment_url()
の戻り値でチェック
テスト用に以下のようなコードを貼り、実際の画像IDを使って URL を出力してみてください。
$image_id = 12345; // 適当な画像IDに置き換え
echo wp_get_attachment_url($image_id);
これで /files/
が出るなら、upload_dir
にフィルターが入ってる可能性大です。
upload_path
とupload_url_path
に問題ないか?
「ネットワーク管理画面 → サイト → 対象のサイト → [設定] タブ」の「upload_path
」と「upload_url_path
」を確認します。画像アップロード先を故意に変更している以外は、記載せずに自動で
wp_sitemeta
テーブルのms_files_rewriting
を確認
データベースの内容をさらに深掘りしたところ、マルチサイトの設定情報を格納しているwp_sitemeta
テーブルが怪しいことに気づきました。
特に、正常なサイトと異常なサイトを比べたところ、ms_files_rewriting
というキーが本番には存在しないことが判明!
ローカル環境のデータベースには、ちゃんと入っていて値が「0」になっていました。
最終解決:ms_files_rewritingを追加
そこで、WP-CLIを使って次のコマンドを実行しました。
WP-CLIで追加
sudo /usr/local/bin/wp db query "INSERT INTO wp_sitemeta (site_id, meta_key, meta_value) VALUES (1, 'ms_files_rewriting', '0');"
wp_sitemeta
に直接1行追加しています。site_id
は通常「1」ですが、マルチサイト環境によって違う場合は適宜変更してください。
データベースで直接追加
WP-DBManegerなどでスクリプトを打つのもありです。※使用後はセキュリティ上プラグインを削除する事をオススメします。
INSERT INTO wp_sitemeta (site_id, meta_key, meta_value) VALUES (1, 'ms_files_rewriting', '0');
※もしマルチサイトで site_id が違う場合は、正しい site_id を入れてください。(通常は「1」です)
これでサーバー側の認識が正しくなり、古いfilesパス問題が解決しました!
nginxのリダイレクト設定を削除
古いパス問題が解決したら、応急処置をしておいたnginxのリダイレクト設定を削除して、sudo systemctl restart nginx
をします。
さらに発生した副問題:ファイルURLの「//」連続問題
直った直後に、メディアのファイルURLを見ると…
https://example.com/wp-content/uploads/sites/21//sites/21/2024/01/IMG_7049.webp
のように、「//」が連続している問題が発生していました。
調査したところ、WordPress管理画面の「設定」→「メディア」→「アップロードするファイルの保存場所」のカスタム設定(upload_path
・upload_url_path
)が空でない場合、こうなることがあると判明。
そこで、この2つの項目を空に設定し直したら、正常なURLに修正されました!
まとめ
今回のトラブル対応の流れはこんな感じです。
blogs.dir内の画像フォルダ構成を変更
データベースの画像URLを置換
nginx設定でリダイレクトの応急処置
wp_sitemetaにms_files_rewritingが存在しないと判明
WP-CLIから直接データベースにINSERTして復旧
URLの「//」問題は設定画面でupload_pathとupload_url_pathを空にして解決
nginxのリダイレクト設定を削除
WordPressマルチサイトはシングルサイトより構造が複雑な分、こういったトラブルも起きやすいですが、原因を一つずつ潰していくことで、ちゃんと復旧できると実感しました!
もし同じように困っている方がいたら、この記事が少しでも役立てば嬉しいです。
この手順で直しましたが、データベースを修正するので、くれぐれもバックアップを忘れないようにしてください。上記の修正によるサイトの損壊や損害は負いません。全て自己責任でお願いします。
(おまけ)使用したWP-CLIコマンドまとめ
データベース内の文字列検索(dry-run)
files
以外に念の為blogs.dir
もないか検索する
sudo /usr/local/bin/wp search-replace 'blogs.dir' '' --dry-run
ms_files_rewriting
を追加する
sudo /usr/local/bin/wp db query "INSERT INTO wp_sitemeta (site_id, meta_key, meta_value) VALUES (1, 'ms_files_rewriting', '0');"
コメント