MENU

【保存版】WordPressマルチサイトの旧ファイルURL問題(/blogs.dir/)を直す方法

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にバグがあり、画像が表示されない現象が起こるというわけです。

ローカルで検証する環境を整える

まずは本番環境をローカルに入れて、データベース内を検証することにしました。

STEP
WordPress直下に移動
cd /var/www/html/your-wordpress-dir
STEP
本番環境のデータをバックアップする

ドメイン直下に行き、WordPressのデータベース丸々WP-CLIでバックアップします。

wp db export backup.sql --allow-root

次に、ローカルにインポートするためのデータ(本番データの wp_userswp_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
STEP
本番データをローカル環境にインポート

ローカル環境はLocalを使用しているので、Localが用意しているシェルを使用します。

本番データの wp_userswp_usermeta を除いてエクスポートしたデータをインポートします。このとき、wp_users / wp_usermeta はローカルにそのまま残るので、ログイン情報は変わりません

wp db import filtered.sql
STEP
問題あるデータベースを検証する

Localにはアプリ上から、データベースを管理できるAdminerとWP-CLIが使用できるシェルコマンドがあります。

Adminerでデータベース内を検証します。

STEP
初期化(確認ダイアログが出るので -–yes でスキップも可能)

もし本番環境をクリーンしたデータベースに入れ替えたいのなら、下記のコマンドでデータベースがリセットされます。

wp db reset --allow-root
STEP
ローカルで修正済みのSQLファイルをインポート

削ぎ落としたデータに入れ替えたいのなら、下記のコマンド。

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/11 は、そのサブサイトの 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_pathupload_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_pathupload_url_path)が空でない場合、こうなることがあると判明。

そこで、この2つの項目を空に設定し直したら、正常なURLに修正されました!

まとめ

今回のトラブル対応の流れはこんな感じです。

STEP

blogs.dir内の画像フォルダ構成を変更

STEP

データベースの画像URLを置換

STEP

nginx設定でリダイレクトの応急処置

STEP

wp_sitemetaにms_files_rewritingが存在しないと判明

STEP

WP-CLIから直接データベースにINSERTして復旧

STEP

URLの「//」問題は設定画面でupload_pathとupload_url_pathを空にして解決

STEP

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');"
よかったらシェアしてね!
  • URLをコピーしました!

コメント

コメントする

This site uses Akismet to reduce spam. Learn how your comment data is processed.

目次