Ubuntu

WordPress きれいな環境にする

ウチには古くから使っているWordPressがあり、アップグレードを繰り返して6.2.2になっている。
この環境を、インポート・エクスポート機能できれいな環境にしようという試み。



広告


最初はHTTPで運営していたが、その当時に調べたやり方で、どうにかHTTPSに変更した。
うちで使っている分には問題なく動いているのだが、データーをエクスポートしてみるとHTTPが残っている。

また、メディアのアップロードディレクトリがwp-content/blogs.dirになっている。
これはだいぶ昔に使われていた場所らしい。こういうのは、みんなと使う場所が違うと、何か問題が起こっても情報が探しづらい。

不整合とまではいえないこの「なんとなくゴミが残った感じ」をきれいにすることにした。

作戦

かなりマニアックな作戦で、一般向きではないが、結果からするとだいたい上手くいく。

稼働中のシステムで、理屈通りにデーターベースをいじって、ディレクトリの移動とかをやれば、それなりに動くだろうとは思う。
でも、プログラムを途中まで追いかけて、面倒になってしまった。色々眺めてデーターにパッチを当てたとしても、それが与える影響を確かめるのは大変。

新しくWordPressを構築し、そこにデーターを放り込めば、きれいな環境ができるはずだ。
きっと便利なサードパーティー製のプラグインが用意されているのだと思うけれども、それらを使わずに、WordPress標準のエクスポート+インポートで実施して、よりクリーンな状態を目指す。

このWordPress標準のエクスポート+インポートは、余所のサーバーからのお引っ越しツールというイメージ。
エクスポートされるデーターには、投稿や固定ページ、コメント、メディア等の情報が書き込まれているが、メディアの実体は含まれていない。
じゃあ、メディアはどうやって取り込むの?というと、インポートするときに、元のサイトからデーターをダウンロードしてくるようになっている。

この特性を考慮して、

名前IPアドレスアクセスURL用途
ダミー環境1192.168.110.113https://www.example.net (本当の名前を隠すマスク)本番環境の再現
ダミー環境2192.168.110.114http://backup.example.net (これは本当にこのURLにした)同じサイトに引っ越すための一時サイト
ダミー環境3192.168.110.115https://www.example.net (本当の名前を隠すマスク)完成した環境

と、環境を3つ作って、データーを順次インポートして行く。

ダミー環境3は、ネイティブにHTTPSで、wp-content/uploadsにメディアを置く、クリーンな環境になるはずだ。
できあがったクリーンな環境を、本番環境でリストアする。

ダミー環境(1)

本番環境と同じドメイン名で動く仮想サーバーを用意し、本番環境のデーターをリストアしたクローン環境。

DockerのWordPress-FPMを使う手順を整理したときに、動作確認までできているので、これを使うことにする。
Ubuntu 22.04 desktopでWordPress-FPM(Docker)が動いている。

ダミー環境(1)の中からクローンしたWordPressにアクセスするために、以下の設定を入れている。

/etc/hosts

192.168.110.113 www.example.net

※ホームラボのDHCPに割り当てられたIPアドレスと、本番環境と同じドメイン名を設定している。

万が一にも本番環境に変な影響がないように、とダミー環境(1)を作成したけれども、エクスポート+インポートのところでこの環境に手が入ることはなかった。
ただ、メディアをダウンロードしてくるときに、ディスクとネットワークに負荷が掛かるだけでなく、結構メモリーを使うように思う。

ダミー環境(2)

こちらも、Ubuntu 22.04 desktopをMinimalでインストールし、DockerでFPMなWordPressを動かす。
作成手順はダミー環境(1)とほとんど一緒だけれど、ApacheはHTTP(非SSL)でサービスを提供している。

ダミー環境(1)への接続

ダミー環境(1)からWordPressの情報をエクスポートし、メディアをダウンロードするので、アクセスができるようにする。

/etc/hosts

192.168.110.113 www.example.net

※ホームラボのDHCPに割り当てられたIPアドレスと、本番環境と同じドメイン名を設定している。

ブラウザでアクセスし、ツール → エクスポートですべてのコンテンツをエクスポートする。
今回はマルチサイトで、2つのサイトをエクスポートした。

コンテナの起動

とりあえず、動いてくれれば良いという構成。
コンテナを起動するところまで、前回記事と同じ。

バインドマウントした/opt/wordpress/etc/phpにあるphp.ini-productionをphp.iniにコピーする。
大きなメディアを抱えているので、アップロードサイズが影響しそうだったので、upload_max_filesizeとpost_max_sizeに適当な値を設定しておく。

Apacheの設定

こちらは、本当にbackup.example.netというサイト名にする。
こちらはSSL証明書がないので、HTTPでアクセスできるようにしている。

$ sudo apt -y install apache2 libapache2-mod-xsendfile

WordPress用の設定ファイルは、こんな感じ。

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

<VirtualHost *:80>
        ServerName backup.example.net
        DocumentRoot /var/www/html

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

        XSendFile on
        XSendFilePath /var/www/html

        <Directory /var/www/html>
                Require all granted
                DirectoryIndex index.php
                AllowOverride FileInfo
                FallbackResource /index.php
                <FilesMatch \.php$>
                        SetHandler proxy:fcgi://127.0.0.1:9000
                </FilesMatch>
        </Directory>
        <Directory /var/www/html/wp-admin>
                FallbackResource disabled
        </Directory>
</VirtualHost>

この設定を有効化しておく。
また、マルチサイトにする場合には、rewriteモジュールが必要なので、有効化しておく。

$ sudo a2dissite 000-default.conf
$ sudo a2ensite wordpress.conf
$ sudo a2enmod rewrite http2 proxy_fcgi
$ sudo systemctl restart apache2

※モジュールを有効化したときには、Apacheの再起動が必要。メッセージが表示されるので、それに従う。

WordPressのインストール

このダミー環境(2)にアクセスができるようにhostsを設定して、WordPressをインストールしていく。

/etc/hosts

192.168.110.114 backup.example.net

※ホームラボのDHCPに割り当てられたIPアドレスと、backup.example.netをセット。

ブラウザで http://backup.example.net にアクセスすると、安全ではない接続ではあるものの、WordPressのインストール画面が表示される。
インポートするときに、ユーザーの名前が重要になってくると思うので、合わせておいた。

移行してくるのはマルチサイトなので、ここでマルチサイトにしておく。
WordPress.org 日本語 / ネットワークの作成

インストール直後でプラグインは有効になっていないはずだが、もし何かを有効にしたなら一旦無効化する。

wp-config.phpにマルチサイトの設定を入れる。

/var/www/html/wp-config.php

...
if ($configExtra = getenv_docker('WORDPRESS_CONFIG_EXTRA', '')) {
        eval($configExtra);
}

/* Multisite */
define( 'WP_ALLOW_MULTISITE', true );

/* That's all, stop editing! Happy publishing. */
...

ダッシュボードにアクセスし直して、ツール → サイトネットワークの設置 に進む。

サブドメインとサブディレクトリが選択できるときと、選択できないときがあるが、その条件はよく分かっていない。
この間まで一度も選択できたためしがなかったが、このメモを作成しはじめたタイミングでは、必ず選択できるようになっている。
(選択できなかったとしても、wp-config.phpに入れるSUBDOMAIN_INSTALLでコントロールできそうな気はする)

ウチのマルチサイトはサブディレクトリなので、サブディレクトリを選択して、インストールボタンをクリックする。

WordPressサイトネットワークの作成画面が表示されるので、指定されたとおりにファイルを編集する。

画面で表示された設定値を、それぞれのファイルに書き込む。

/var/www/html/wp-config.php

...
if ($configExtra = getenv_docker('WORDPRESS_CONFIG_EXTRA', '')) {
        eval($configExtra);
}

/* Multisite */
define( 'WP_ALLOW_MULTISITE', true );

define( 'MULTISITE', true );
define( 'SUBDOMAIN_INSTALL', false );
define( 'DOMAIN_CURRENT_SITE', 'backup.example.net' );
define( 'PATH_CURRENT_SITE', '/' );
define( 'SITE_ID_CURRENT_SITE', 1 );
define( 'BLOG_ID_CURRENT_SITE', 1 );

/* That's all, stop editing! Happy publishing. */
...

/var/www/html/.htaccess

...
<IfModule mod_rewrite.c>
#RewriteEngine On
#RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
#RewriteBase /
#RewriteRule ^index\.php$ - [L]
#RewriteCond %{REQUEST_FILENAME} !-f
#RewriteCond %{REQUEST_FILENAME} !-d
#RewriteRule . /index.php [L]

RewriteEngine On
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteBase /
RewriteRule ^index\.php$ - [L]

# add a trailing slash to /wp-admin
RewriteRule ^([_0-9a-zA-Z-]+/)?wp-admin$ $1wp-admin/ [R=301,L]

RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
RewriteRule ^([_0-9a-zA-Z-]+/)?(wp-(content|admin|includes).*) $2 [L]
RewriteRule ^([_0-9a-zA-Z-]+/)?(.*\.php)$ $2 [L]
RewriteRule . index.php [L]
</IfModule>
...

編集したら、画面下の方にある「ログイン」リンクをクリックし、ログインするとマルチサイトになっている。
必要分だけサイトを追加する。

メディアのインポート

WordPressのインポートはプラグインで実装されていて、2023年7月16日時点で以下の特徴を持っていた。

  • 本番環境がエクスポートしたデーターには、投稿はすべて含まれているが、メディアは含まれていない。
    インポートするときに、本番環境からダウンロードする形式。
    これは、自分で完全にはコントロールできないようなサービスから引っ越してくるときには合理的だと思う。
  • インポートする先について厳しくチェックが行われ、安全でないと判断されるとインポートが失敗する。
    試して分かったのは、名前解決した結果がローカルIPアドレスだとエラーになること。
    何故ローカルIPアドレスが危険なのかが分からないが、そういう結果だった。
  • エクスポートデーターには投稿や固定ページなどが含まれるが、その中のメディアへのリンクは、元のサイトを指している。
    メディアをインポートしても、このリンクが新しいサイトに書き換えられることはない。
  • 自動スケーリング機能によって画像が縮小されていると、縮小された画像しか取ってこない。
    IMG_NNNN.jpgという元画像の場合、IMG_NNNN-scaring.jpgを取りに行き、IMG_NNNN-scaring-1.jpgという名前で保管する。
    IMG_NNNN-scaring-1.jpgという元画像の場合、IMG_NNNN-scaring-1.jpgと同じ名前で保管する。

今回は、なんとしても標準機能でインポートして、きれいな状態を作り出したかったので、厳しいチェックを外すためのフィルターを入れることにした。
本番環境に入れると危ないってことだと思うので、あくまでもローカルで使うだけ。
Stack Exchange / Bypass wp_safe_remote_get()?

自動スケーリング機能によって画像のファイル名が変えられるのが嫌なので、これを止めるフィルターも入れよう。
smartwp / How to Disable Large Image Scaling in WordPress

さて、これらのフィルターをどこに入れようか…
デフォルトのテーマはTwenty Twenty-Three、functions.phpがない(珍しいかも)ので、functions.phpを新設して設置。
<?phpで始まっているんだから、閉じるんじゃ?とか余計な事は考えない、お作法なのでしょう。

/var/www/html/wp-content/themes/twentytwentythree/functions.php ※新設

<?php
function turn_off_reject_unsafe_urls($args) {
        $args['reject_unsafe_urls'] = false;

        return $args;
}
add_filter( 'http_request_args', 'turn_off_reject_unsafe_urls');

add_filter( 'big_image_size_threshold', '__return_false' );

新設したファイルのオーナーを変えておく。

$ sudo chown www-data:www-data /var/www/html/wp-content/themes/twentytwentythree/functions.php

最初に記したように、自動スケーリングされた画像をインポートするとき、原本ではなく縮小された画像を取ってきていた。
これは、エクスポートされるデーターでは、画像の原本ではなく、自動スケーリングされた画像を指しているからだった。
WordPressの日記には、デジイチで撮影した写真が貼り付けてあるので、縮小された画像だけを持ってこられても困る。
そのため、エクスポートされたデーターに以下の改変を加える。

"-scaled.jpg" → ".jpg"

※jpeg等、jpg以外の拡張子がある場合は… "-scaled." を "" に変換しても良いかも(試していない)。

ダミー環境(2)のダッシュボードに行き、ツール → インポート に移動する。
そこに、WordPressという項目があり、今すぐインストールのリンクがあるのでクリックすると、プラグインがインストールされて有効化される。

インポーターの実行をクリックし、WordPressのインポート画面が表示されたら、ファイルを選択。
ファイルをアップロードしてインポートをクリックすると、投稿者の割り当て、添付ファイルのインポートが表示されるので、適切に選択して実行をクリックする。

インポート中にエラーが発生したが、処理は継続しており、すべてのファイルがインポートできた。
(エラー発生時に急いでメディアにアクセスし、346件のインポートができていることは確認したので、その手前のファイルを確認したけれども問題はなかった。)

Internal Server Error

The server encountered an internal error or misconfiguration and was unable to complete your request.

Please contact the server administrator at [no address given] to inform them of the time this error occurred, and the actions you performed just before this error.

More information about this error may be available in the server error log.

----- <水平線> -----
Apache/2.4.52 (Ubuntu) Server at backup.example.net Port 80

ダミー環境(1)(2)共にHDDで作成していて、ダウンロードしたファイルは7.1GB、処理時間は30分くらいだった。

投稿その他のインポート

メディアをインポートするときに、投稿や固定ページ、コメントなどがすべてインポートされる。
だけれども、例えば投稿の中にあるメディアへのリンクは、ダミー環境(1)を指している。

画像が見えた、OK、OK、と思っても、それはダミー環境(1)の画像や動画を見ているのであって、ダミー環境(2)に取り込んだものではない。
ダミー環境(1)をシャットダウンすると、画像や動画は見えなくなる。

WordPressをよく知る人なら、データーベースを書き換えてしまうことだろう。
でも、WordPressに関して持っている情報が少なすぎて、仮に書き換えたとしても、その先上手くいくかどうかが見通せない。

そこで、投稿、固定ページ、コメントを全て削除し、インポートするデーターをダミー環境(2)に書き換えて、再度取り込むことにした。

"https://www.example.net" → "http://backup.example.net"

さらに、ウチのサーバーは古くから使っているので、メディアは旧形式のwp-content/blogs.dirに保管されている。
ダミー環境(2)では、新形式のwp-content/uploadsに保管されているので、これも書き換えておく。
旧形式では files が内部で置き換えられていたが、新形式で置き換えなしでファイルが特定できるようだ。

https://oldsite.example.com/hoge/files/2023/02/hoge.jpg
https://newsite.example.com/hoge/wp-content/uploads/sites/2/2023/02/hoge.jpg

※赤文字2のところは、サイトID。

書き換えが終わったら、インポートする。
この時には、既にメディアのダウンロードは済ませているので、チェックを入れない。
投稿や固定ページ、コメントだけを取り込んで行く。

メディアをインポートすると、メディアのファイルが2重(-1という重複しない名前が付けられる)になってしまうので注意。

これで、ダミー環境(2)が完成した。

ダミー環境(3)

こちらも、Ubuntu 22.04 desktopをMinimalでインストールし、DockerでFPMなWordPressを動かす。

ダミー環境(2)への接続

この環境でも、/etc/hostsを使ってアクセス先を設定する。

/etc/hosts

192.168.110.114 backup.example.net
192.168.110.115 www.example.net

※ホームラボのDHCPに割り当てられたIPアドレスと、ダミー環境(2)、および、ダミー環境(3)のドメイン名をセット。

WordPressとApacheの設定

DockerのWordPress-FPMを使う手順で作り込む。
WordPressは本番環境と同じURLでセットアップし、マルチサイトならばマルチサイトの設定までしておく

長い上に全く同じことをするので、省略。

メディアのインポート

ダミー環境(1)では -scaled.jpg のような置き換えが、原本のイメージのダウンロードを阻害していた。

ダミー環境(2)では -rotated.jpg のような置き換えが起きていることが分かった。
例えば、デジカメを回転させてポートレートを撮影すると、画像に記録された情報(多分、EXIFタグの0x0112 Orientation)を元に、WordPressが画像を回転させてくれているようだ。

ダミー環境(1)からのインポートで必要な回転が行われたのだから、ダミー環境(2)からのインポートでも同じ処理をしてくれるはずなので、元画像をインポートしよう。
そのために、インポートするデーターに以下の改変を加える。

"-rotated.jpg" → ".jpg"

※jpeg等の拡張子がある場合は… "-rotated." を "" に変換しても良いかも(試していない)。

ダミー環境(2)に記した手順で、/var/www/html/wp-content/themes/twentytwentythree/functions.php を新設してインポートすれば、メディアが取り込まれる。

投稿その他のインポート

投稿、固定ページ、コメントを削除し、インポートデーターに以下の改変を加える。

"http://backup.example.net" → "https://www.example.net"

インポートで投稿その他を取り込むことができ、これらからのメディアへのリンクも、ダミー環境(3)を指すようになる。
メディアをインポートすると、メディアのファイルが2重になってしまうので注意。

不要なデーターの削除

実は、WordPressをインストールすると、自動で登録されるものがいくつかある。

  • 投稿: Hello world!
  • 固定ページ: サンプルページ、プライバシーポリシー
  • コメント: WordPress コメントの投稿者

これらは要らないので、削除してしまう。

テーマの復元

使用していたテーマを、ディレクトリごとコピーしてくる。

基本的にはディレクトリを持ってきて、管理者でテーマを有効化させれば使えるようにはなるのだけれど、いかんせんテーマが古かった。
導入当時にあった何らかのデーターが、まっさらから立ち上げた環境には作られないらしく、ワーニングを吐いたりしている。
これはもう、新しいテーマに差し替えざるを得ないだろう。
(今となっては確かに古ぼけているとはいえ、基本的にカワイイ感じだったんだよなぁ、イマドキそんなテーマは探しても見つからないよ…)

プラグインの復元

使用していたプラグインを、ディレクトリごとコピーしてくる。

これもディレクトリごと持ってくれば使い始められるはずなんだけれど、更新されているものと、更新が止まっているものがある。
更新が止まっているものについて、一部手直しが必要だった。

get_currentuserinfoは非推奨

デバッグログを出力していると、このエラーがずっと出ている。

Deprecated: 関数 get_currentuserinfo は、バージョン 4.5.0 から非推奨になりました ! 代わりに wp_get_current_user() を使用してください。

これを修正するには、単に関数を置き換えれば良いとのこと。
stack overflow / get_currentuserinfo is deprecated since version 4.5! Use wp_get_current_user() instead

探してみると、重宝している「ブログをメンバー専用にする=ログインしないと見られないようにする」というプラグインで、だいぶ前に開発が終了しているようだ。
今も問題なく機能しているけれど、裏ではこんなワーニングが出続けていたのね。

wp-content/plugins/wordpress-access-control/wordpress-access-control.php

...
    if (is_user_logged_in()) {
      wp_get_current_user(); //get_currentuserinfo();
...

※赤文字部分を追加した。

当面はこの修正でいいとして、いずれは新しい別のプラグインを探すのかな。

設定を手作業で復旧する

ダミー環境(1)のすべての設定画面を見て、ダミー環境(3)に復元していく。
もちろん、最初にWordPressを構築したときとは、サーバーも、ネットワークも、取り扱うデーターも色々と違っているので、この機会に見直すのもあり。

参照した画面は以下、当サイトで手直しをしたものにフラグを立てている。ご参考まで。

画面手直し何を見たか
サイトネットワーク管理 → サイトどんなサイトがあるか、移行対象とするサイトはどれか。古いのは要らないはずだけど、念押し確認。
サイトネットワーク管理 → サイト → [移行するサイト]作成日時、属性、ユーザーが同じになっていること。
設定タブでは、サイトの細かな設定(これはwp_sitemeta?)を確認。
サイトネットワーク管理 → ユーザー記事を投稿していないユーザーが作られていなかったので、追加。
そろそろ家族全員を特権管理者にしてもいいかな、って思った。
サイトネットワーク管理 → テーマ使われているテーマを確認して、必要分を移行する。
サイトネットワーク管理 → プラグイン使われているプラグインを確認して、必要分を移行する。不要なプラグインは削除する。
サイトネットワーク管理 → 設定アップロードファイルの最大サイズを拡張した。
アップロード可能なファイル形式がかなり増えていてびっくり。
各サイト → 投稿 → 投稿一覧投稿した記事の数を確認。
各サイト → 投稿 → カテゴリーカテゴリーの一致を確認。見たところ、Uncategorizedは未分類に変わっていた。
そのせいか、未分類が2つできているサイトがあったので整理した。
各サイト → 投稿 → タグタグの数を確認。
各サイト → メディアメディアの数を確認。
各サイト → リンク新しい環境にはなかった。使っていないのでOK。
各サイト → 固定ページ固定ページの数を確認。
各サイト → コメントコメントの数を確認。
各サイト → 外観 → テーマメインで使っていたテーマを変更。
ウィジェットについて、グーテンベルグで編集するように変わってしまったものがあった。
以前、固定ページへのリンクをメニューっぽく張っていたのだけれど、今回はメニューで対応。
各サイト → プラグインサイトに適用するプラグインを確認。
各サイト → ユーザーサイトネットワークで追加したユーザーが登録できていなかった。
これは、サイトネットワークでサイトのユーザーを追加することで対応。
各サイト → ツール特になし。
各サイト → 設定これは、WordPress運営に関わる結構な設定がある。
1つ1つ確認して移行する。
インターネットで情報公開している方は、パーマリンクの設定等が重要だと思われる。
プラグインなんかの設定が表示される場合もあるので、しっかりと移していく。

ちなみに、個別サイトのダッシュボードから「リンク」という画面にアクセスできるけれど、新しく作った環境には「リンク」という画面がない。
これはLinks Managerというらしい。バージョン3.5から、デフォルトでは表示されなくなったようで、プラグインとして提供されているようだ。
WordPress.org / Links Manager

一回も使ったことのない機能だけれど、一応メモしておく。

テーマの調整

Twenty Twenty Threeに作成したfunctions.phpを削除

ローカル環境からのインポートのために、接続先を厳しくチェックするのをやめるフィルターを追加しているはず。
具体的には、Twenty Twenty Threeのテーマにfunctions.phpはなかったので、新規に作ってフィルターを追加していた。

このファイルを削除する。

$ sudo rm /var/www/html/wp-content/themes/twentytwentythree/functions.php

これで安全に戻った。

子テーマの作成

メディアの自動スケーリングは、日記として使うに場合には、あったら困る機能のように思える。
新しくインストールしたテーマに子テーマを作成して、メディアの自動スケーリング機能を止めるフィルターを入れる。

$ cd /var/www/html/wp-content/themes
$ sudo -u www-data mkdir child-<theme name>

※<theme name>は、利用するテーマの名前を想定。
※でも、ディレクトリの名前は、実際にはアルファベットであれば、だいたい大丈夫だと思う。

作成したディレクトリに、style.cssを作成し、以下の情報を埋めていく。
WordPress Developer / Child Themes

最低限必要なのがこの2つだそうで、残りは必要な分だけ書いておけば良いようだ。

  • Theme Nameが、この子テーマの名前。
  • Templateが、親テーマの名前。

/var/www/html/wp-content/themes/child-<theme name>/style.css ※新規作成。

/*
Theme Name:   Twenty Fifteen Child
Theme URI:    http://example.com/twenty-fifteen-child/
Description:  Twenty Fifteen Child Theme
Author:       John Doe
Author URI:   http://example.com
Template:     twentyfifteen
Version:      1.0.0
License:      GNU General Public License v2 or later
License URI:  http://www.gnu.org/licenses/gpl-2.0.html
Tags:         light, dark, two-columns, right-sidebar, responsive-layout, accessibility-ready
Text Domain:  twentyfifteenchild
*/

説明用に書かれたcssを転記してきた

functions.phpのサンプルが載っていたけれども、テーマによって書かなければならないことは違うようだ。

インストールしたテーマがたまたま子テーマだったので、親テーマもインストールされていた。
Templateを親テーマに書き換え、子テーマのfunctions.phpを見ながらこんなのを書いたら、上手く動いた。

/var/www/html/wp-content/themes/child-<theme name>/functions.php ※新規作成

<?php
function my_child_<theme name>_theme_setup() {
    load_child_theme_textdomain( 'child-<theme name>', get_stylesheet_directory() . '/languages' );
}
add_action( 'after_setup_theme', 'my_child_<theme name>_theme_setup', 100 );

function my_enqueue_scripts() {
    wp_enqueue_style( '<theme name>', get_template_directory_uri() . '/style.css' );

}
add_action('wp_enqueue_scripts', 'my_enqueue_scripts');

add_filter( 'big_image_size_threshold', '__return_false' );

先程の説明ページをざっと斜め読みすると、

  • functions.phpは子テーマのものが先に読み込まれ、後から親テーマのものが読み込まれる。
  • それ以外のファイルは、親テーマのファイルを子テーマのファイルが上書きする。

とされていて、何か改造をしたいときには、親のファイルをコピーしてきて手を加える、ということで良さそうだ。

仕上げ

テーマを変えたこともあって、色々と変えておかなきゃならないことがあった。

  • SEO対策で、表示されるのが「更新日」になっている。
    日記なので「投稿日」の方が重要だったりするから、その表示がされるように設定する。
  • 昔は固定ページへのリンクをヘッダーブロック(?)に貼っていたが、今はメニューを設定しておくことになる。
    メニューに固定ページをセットしておけば、今までと同じように動作する。
  • 今のテーマはアイキャッチ画像があると格好良く表示してくれる。
    そんなの設定してなかったなー、ということで、過去の投稿にもアイキャッチ画像をセットしておくといい。
    (これで、冒頭の更新日表示に気が付いた…)

後は好みの雰囲気で表示がされるように、色を変えたり、文字の大きさを変えたりと、適当に設定して良い感じに仕上げる。

本番環境に移すためのバックアップ

ダミー環境(3)にきれいな状態ができあがっているので、本番環境に移すためにバックアップする。

  • WordPressのコンテナを止める(MariaDBのコンテナは止めない)。
  • データーベースのダンプを取る。→ /opt/wordpress/backups へ
  • /opt/wordpressと、/var/www/htmlを固める。
  • WordPressのコンテナを起動する。

これらを実行して行く。

$ cd /opt/wordpress
$ sudo docker compose stop wordpress

データーベースのダンプを取得。

$ cd
$ sudo docker exec wordpress_db \
mariadb-dump -u wordpress --password=wordpress --single-transaction --routines wordpress \
| sudo tee /opt/wordpress/backups/wordpress.dmp > /dev/null

/var/www/htmlと/opt/wordpressを固める。
展開時にいきなりこれらの場所を更新しないように、先頭の / が入らないようにしている。
これが良い考えなのかどうかは分からないが、色々と確かめてから操作ができるようにはなるだろう。

$ cd
$ sudo tar -jcvf backup.wordpress.tar.bz -C / var/www/html opt/wordpress

バックアップが取れたので、WordPressを再開する。

$ cd /opt/wordpress
$ sudo docker compose up -d wordpress

この手順を実行すると、ホームディレクトリにバックアップファイルができている。
このファイルをSCPなどで取り出して、本番環境に持って行く。

バックアップファイルが8GB程あったが、Tera Termでは途中で止まってしまって取り出すことができなかった。
原因は良く分からなかった。
仕方がないので、仮想PCのネットワーク接続先を変えて、本番環境からSCPでファイルを取り出した。

あ!Apacheのconfファイルを忘れていた…
あれは、テキストファイルだし、めったに変更することもないだろうから、どっかにメモしておけばいいかなー。

調べたこと

大きな画像がインポートできない

自動スケーリングが影響し、投稿に貼り付けた画像の解像度が下がり、ファイル名が変わっている。
この問題が発生しないように、本編では、WordPressのエクスポートデーターのファイル名から -scaled を除去した。

情報区分ダミー環境(1)ダミー環境(2)ダミー環境(3)
ドメイン本番環境backup.example.net本番環境
実ファイル名IMG_2364.jpgインポートされないインポートされない
メディアライブラリでの見え方IMG_2364-scaled.jpg
2560 x 1707
元の画像 IMG_2364.jpg
IMG_2364-scaled.jpg
2560 x 1707
元の画像 リンクなし
IMG_2364-scaled-1.jpg
2560 x 1707
元の画像 リンクなし
xmlでの見え方なしIMG_2364-scaled.jpg, 他IMG_2364-scaled-1.jpg, 他

WordPressは5.3(2019年11月21日リリース)から画像サイズを圧縮する機能がデフォルトで動作するようになったそうだ。
smartwp / How to Disable Large Image Scaling in WordPress

scaledという名前が付いたファイルは、ウチでは2019年10月にはなく、2020年3月には登場。
5.3のリリース時期と合致している。

日記には写真が載っていて、それはデジイチで撮影しているから、元の画像が見られないってのは残念ではある。
自動スケーリングが理由で、お引っ越しで画質が下がり、ファイル名が変わるということだ。

そもそも、WordPressって、普通に画像を置いたら小~大のサムネイルを配置するんじゃなかったっけ?
元の画像にたどり着くには、ギャラリーにして、メディアへのリンクにして…と、数々の手間を掛けなければならない。そんな具合で、ページが軽くなるように色々と仕組まれている訳で、なんで自動スケーリングなんてのが必要なんだろう?

不思議だが、面倒なので理由は探さない。WordPressでそういう情報を探すのって…多分不可能だと思う。

アップロードディレクトリが変わったこと

最初にDockerのWordPressを動かしたとき、メディアが上手く表示できない問題が発生していた
原因は、X-Sendfileの設定がちゃんとできていなかったことだが、原因にたどり着くまでに色々調べていた。

その中で、アップロードディレクトリが変わった、というのがある。

もしかして、メディアのディレクトリが上手く見つけられなくなっている?そういえば、いつからかアップロードディレクトリが変わっている気がするな…と思ってたどり着いたのがココ。
UpdraftPlus / I am restoring a pre-WordPress-3.5 multisite into a 3.5-or-later multisite – what happened to my blogs.dir?

これはとても便利なプラグインを提供しているようで、マルチサイトで発生しているディレクトリの違いと、その対応方法について説明してくれている。その中で、WordPressは3.5からアップロードディレクトリが変わったことを教えてくれた。

その他、アップロードディレクトリが変わったことに関する問題や、アップロードディレクトリを変えたいという情報も探してみていた。
Stack Exchange / How to use 'blogs.dir' as media upload instead of 'uploads' directory in WordPress multisite setup
Stack Overflow / Converting from storing uploads in wp-content/blogs.dir to wp-content/uploads/sites
Stack Overflow / change wordpress image upload to another directory in public_html

アップロードディレクトリを変える方法は色々あるみたいなので、メモとして残しておく。

エクスポートとインポート

以前にもエクスポートとインポートを試していて、同じような結論に達していた気がする。
これは、他のサービスからのお引っ越しツールなんだなぁと。
WordPress Support / Export Media Library
WordPress Support / Didn’t export images at all

その時にも、メディアのURLが引っ越し前のサイトになっている…といって困ったことをうっすらと思い出した。
標準機能でインポートできる!と説明しているサイトでも、このことには言及していないケースもあるみたい。

今回整理した手順では、エクスポートされたデーターに手を入れてインポートするという、ちょっとしたアクロバットをしながら、とりあえず引っ越しができるようになった。

本当はもっと素晴らしい手順があるかもしれない。
プラグインを使え!ということかもしれない。

メディアがインポートできない

投稿はインポートできるものの、メディアがインポートできない問題が発生していた。

メディア のインポートに失敗しました “hoge.jpg”: 次のエラーによりリクエストが失敗しました: 有効な URL ではありません。 (http_request_failed)

インポートファイルを見てみたら、guid isPermaLinkの値が

<guid isPermaLink="false">http://www.example.net/hoge/files/2013/07/hoge.jpg</guid>

となっていた。
HTTPではじめたこの環境、途中でどうにかHTTPSに対応したつもりだったけれど、中にまだHTTPの部分が残っているらしい。
完全にHTTPSへの引っ越しができていなかったのか…

この問題が、今回の手順を整理する最後の一押しとなった。

この問題自体は、インポートファイルのhttp部分をhttpsに書き換えれば先に進む。

サイトネットワークの作成画面が見られない

サイトネットワークを作成するときに、wp-config.phpや.htaccessの設定を教えてくれる画面、どういう条件なのかはよく分からないのだけれど、いつの間にか見られなくなる。

  • 最初は、サイトネットワーク管理 → 設定 と選択すると、サブメニューとして「サイトネットワーク設定」と「サイトネットワークの設置」が表示され、サイトネットワークの設置でこの画面が表示される。
  • そのうち、サイトネットワーク管理 → 設定 と選択しても、サブメニューなしで「サイトネットワーク設定」が表示されるようになる。

後からこの画面を表示させたいときには、/wp-admin/network/setup.phpを手入力すれば、もう一度見ることができた。

blogs.dirからの卒業(失敗)

新しいWordPressは、アップロード用のディレクトリとして、wp-content/blogs.dirではなく、wp-content/uploadsを使うらしい。
これがいつからなのか、探してみたけれども、これ!という情報は見つからなかったが、こちらのプラグインで3.5以降で変わっていると説明してくれている。
UpdraftPlus / I am restoring a pre-WordPress-3.5 multisite into a 3.5-or-later multisite – what happened to my blogs.dir?

新しい状態にするべく、辿るには辿ってみたんだけれど…

まず、blogs.dirという文字列がどこにあるのか探してみた。
そうすると、ただ1つのファイルが見つかる。

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.
        add_filter( 'default_site_option_ms_files_rewriting', '__return_true' );
    
        if ( ! get_site_option( 'ms_files_rewriting' ) ) {
                return;
        }
...

ココを通過すると、

  • UPLOADBLOGSDIR が wp-content/blogs.dir になる。
  • UPLOADS が wp-content/blogs.dir/2/files になる。※2はサイトID(マルチサイト)
  • BLOGUPLOADDIR が wp-content/blogs.dir/2/files/ になる。

になるのだけれど、サイトオプションのms_files_rewritingがどうなっているのか調べているようだ。

これが、こんなことになっていて…

wp-includes/option.php

function get_site_option( $option, $default_value = false, $deprecated = true ) {
    return get_network_option( null, $option, $default_value );
}
...

同じファイルにその関数があり…

wp-includes/option.php

function get_network_option( $network_id, $option, $default_value = false ) {
    global $wpdb;

...
        if ( ! isset( $value ) || false === $value ) {
            $row = $wpdb->get_row( $wpdb->prepare( "SELECT meta_value FROM $wpdb->sitemeta WHERE meta_key = %s AND site_id = %d", $option, $network_id ) );

            // Has to be get_row() instead of get_var() because of funkiness with 0, false, null values.
...

といった具合で、データーベースに問い合わせをしている。
デバッグログを出して、どんなSQLになるのかを見てみると…

SELECT meta_value FROM wp_sitemeta WHERE meta_key = 'ms_files_rewriting' AND site_id = 1

という具合だった。サイトIDは2なのだけれど、ネットワークIDの1が使われている。

検索してみたところ、中身は空っぽだった。

MariaDB [wordpress]> select meta_value from wp_sitemeta where meta_key = 'ms_files_rewriting' and site_id = 1;
Empty set (0.001 sec)

ちなみに、他の少し前に作ったサイトはどうかというと、0が設定されていた。

MariaDB [wordpress]> select meta_value from wp_sitemeta where meta_key = 'ms_files_rewriting' and site_id = 1;
+------------+
| meta_value |
+------------+
| 0          |
+------------+
1 row in set (0.002 sec)

さて、レコードがなかった場合、以下の処理に進んでいく。

wp-includes/option.php

function get_network_option( $network_id, $option, $default_value = false ) {
...
                /** This filter is documented in wp-includes/option.php */
                $value = apply_filters( 'default_site_option_' . $option, $default_value, $option, $network_id );
            }
...

ms_upload_constants関数でtrueが返るようにフィルターが追加されている。
だから、trueが戻ってくるという流れだった。

ということで、どうやら新しく作ったWordPressのデーターベースには、wp-sitemetaにms_files_rewriting=0というデーターが設定されているようだ。
じゃあ、それを足してみよう。

MariaDB [wordpress]> describe wp_sitemeta;
+------------+--------------+------+-----+---------+----------------+
| Field      | Type         | Null | Key | Default | Extra          |
+------------+--------------+------+-----+---------+----------------+
| meta_id    | bigint(20)   | NO   | PRI | NULL    | auto_increment |
| site_id    | bigint(20)   | NO   | MUL | 0       |                |
| meta_key   | varchar(255) | YES  | MUL | NULL    |                |
| meta_value | longtext     | YES  |     | NULL    |                |
+------------+--------------+------+-----+---------+----------------+
4 rows in set (0.001 sec)

MariaDB [wordpress]> insert into wp_sitemeta(site_id,meta_key,meta_value) values (1,'ms_files_rewriting',0);
Query OK, 1 row affected (0.001 sec)

これで、2つ目のサイトにアクセスしてみると、デバッグログに以下が出力されている。

15-Jul-2023 06:04:52 UTC] PHP Fatal error:  Uncaught Error: Undefined constant "BLOGUPLOADDIR" in /var/www/html/wp-includes/ms-files.php:26
Stack trace:
#0 {main}
  thrown in /var/www/html/wp-includes/ms-files.php on line 26

ここでは、BLOGUPLOADDIRという変数を使ってファイル名を生成しようとしていたが、未定義。
もう、最初に作ったときからこうなることは決まっていたのだろう。

これはもうダメだ…ということで、追加したレコードの値を1に書き換えて、新しいWordPressを作り直すことにしたのだった。

MariaDB [wordpress]> update wp_sitemeta set meta_value=1 where site_id=1 and meta_key='ms_files_rewriting';
Query OK, 1 row affected (0.001 sec)
Rows matched: 1  Changed: 1  Warnings: 0

これを調べたずーっと後で、サイトネットワーク管理で、サイトの設定を見てみたところ、

設定項目:upload_path , 設定値:wp-content/blogs.dir/2/files

というのが見つかった。
この設定を変えたとしても、恐らくはファイルをアップロードするときに初めて効いてくるのであって、今までに登録したメディアについては、データーベースの情報を書き換えなければ変わらないと思われる。実際に変えてみたけれども、メディアが置いてある場所は変わらなかった。

作り直さないと上手くいきそうもない、という結論は変わらなかった。

孫テーマは作れない

親テーマは必要なWordPressのテンプレート・アセットをすべて含んでいる。
子テーマは、親テーマの外観と機能を継承し、任意の部分を変更するために使用できる。
とされている。
WordPress Developer / Child Themes

子テーマを作る時には、完全な親テーマが必要ということなので、親テーマとして子テーマを指定することはできない。
つまり孫テーマは作れない、ということになる。

これいいな、と思って選んでインストールしたテーマが子テーマだった。
テーマ作成を商売にしている人達は、

  • 新しいテーマが次々と生まれる中で、売り出したテーマをどうにかして人の目に付くようにしたい。
  • 子テーマをインストールすると、親テーマも一緒にインストールされるようになっているから、親テーマのダウンロード数を延ばすのにもちょうどいい。

といった理由で子テーマをリリースしているのではないかと予想した。

子テーマを作って、メディアの自動スケーリングを止めよう!と思って、子テーマを作ったらエラーが発生したので気付いた。
親テーマに切り替えたところ、ほとんど同じ画面になったから、子テーマに入れた設定をもう一度入れてみよう。

とても良いテーマだから、商売が上手くいって、継続的にこのテーマが更新されることを祈るのみ。

mod_rewriteでやっていること

毎回コピペするだけで、中身がなんなのかを考えたことがなかった。
今回のマルチサイトの場合の設定で、何をしているのかを確認してみた。

.htaccessに書いたことは、そのディレクトリと、そのディレクトリ配下のディレクトリすべてに適用される。

ディレクティブ効果
RewriteEngine OnリクエストされたURLをその場で書き換える機能をオンにする。
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]HTTPのリクエストヘッダーAuthorizationの値を、環境変数HTTP_AUTHORIZATIONにいれる。
Authorizationには、認証方式と認証情報が入る。
※今はApacheで認証をしていないので、中身が入ることはなかった。
書き換えは実行しない(- が指定されている)。
RewriteBase /書き換え後の先頭に / が付けられる。
RewriteRule ^index\.php$ - [L]/index.phpを要求されたら、それ以上ルールを適用しない。
書き換えは実行しない。
RewriteRule ^([_0-9a-zA-Z-]+/)?wp-admin$ $1wp-admin/ [R=301,L]メインサイト、または、サブサイトのwp-adminで終わるURLが要求されたら、最後に/を付けてリダイレクトし、それ以上ルールを適用しない。
レスポンスステータスコードは301 Moved Permanently。
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
要求されたURLがファイルを指し示している、または、ディレクトリを示している場合、書き換えは実行せず、それ以上ルールを適用しない。
RewriteRule ^([_0-9a-zA-Z-]+/)?(wp-(content|admin|includes).*) $2 [L]wp-content等の手前にサブディレクトリが付いていたら削除し、それ以上ルールを適用しない。
RewriteRule ^([_0-9a-zA-Z-]+/)?(.*\.php)$ $2 [L]phpプログラムファイルの手前にサブディレクトリが付いていたら削除し、それ以上ルールを適用しない。
RewriteRule . index.php [L]これまでの条件に合致しない要求(何か適当なURLが指定された)は、index.phpに置き換えて、それ以上ルールを適用しない。
適当なURLが指定されたら、メインサイトのトップページを表示させているようだ。

Apacheで認証を行ったときに、その情報がリクエストヘッダHTTP:Authorizationに付与される。
このヘッダーが付いていたとき、Apacheはセキュリティの観点でその情報をCGIに渡さない設定になっているので、RewriteRuleを使って環境変数HTTP_AUTHORIZATIONに保存しようとしているということだった。
serverfault / RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}],what does it mean?

サブサイトで色々とやっているけれども、WordPressの中でそう処理をしているだけで、Apacheではサブディレクトリを取り去っている。
そうしておかないと、サブサイトごとにプログラムを配置しなきゃならないから、なるほどなという感じ。

また、改めて確認してみると、適当なURLを入れると、確かにメインサイトのトップページが表示される。
最後のRewriteRule指定だけでなく、ApacheでもDirectoryIndexでindex.phpを指定しているから、必ずトップページが表示されるようになっている。
これを404にするのは…テーマを上手くカスタマイズするってことになると思われる。

さいごに

WordPressの話の多くは、同じ情報が果てしなくたくさんある or 手がかりはあるけれども答えがない、のどちらかであることが多い。
日本語で探すと前者、英単語で探すと後者が多いイメージを持っているが、実はあまり変わらないのかもしれない。

そんな中で、一風変わった情報を探すのは難しい。
blogs.dirがuploadsに変わったのはいつのバージョンか、なんていう情報も、本家では見つけられなかった。

じゃあ、ChatGPTに聞いてみるか…と、GPT4ベースと聞いているBingチャットで聞いてみた。

  • blogs.dirがuploadsに変わったのは3.5だが、示された公式のページにはその情報がなかった。
    そこにないから、情報が書かれている公式のページをもう一回教えて、と繰り返して聞いたけれども、示されたページは1つだけで、その情報はなかった。
  • blogs.dirをuploadsに変えた理由は、セキュリティが理由とのことだが、それがどんな問題なのかは知らなかった。

ということで、この情報を見つけることはできなかった。そういう風には作られていないのかもしれない。

ところで、先日、このBingチャットで「とある質問」をしたら「当サイトの情報が含まれる」的な回答が得られた。回答の文言の後ろに、当サイトのリンクが貼られているので、そういう解釈をした。ところが、

  • そんなことは書いていない。不安になって、リンクを辿って確かめたけれども、そんなことは一切書いていない。
  • ウチで書いた情報は一切教えてくれていない。

といった状態で、ちょっと困りものだなと思うのだった。

情報を探すことについて、こんなことをつらつらと考えながら…
知っている限り、見た限りで試して答えを出す、という方法で記事を投稿している当サイトは、そこが限界点。もっとちゃんと調べれば、もっと良い方法で何かが実現できるかもしれない。
過去の自分の記事が笑っちゃうくらいそれで、今の記事もきっと未来の自分が笑うのだろう。

結局、本気で情報を探したいのならば、時間を掛けてゆっくりと各種文献をあさるしかない。
掛けた手間は、知っていることの増加であり、ホームラボのシステム運用での確信になるから、決して無駄になることはないだろう。と、自分に言い聞かせてみたりして。

広告

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