アドレス変更したらWordPressが壊れた

WordPressが壊れた

WordPressのIPアドレス変更やドメイン移行等を行った場合、WordPressが壊れる場合があります。その際の復旧手順を記します。
※備忘録兼ねてます。

はじめに

先日の WordpressをEC2にインストールする に続いてWordPress関連です。

WordPressを利用したテストサイトの構築を行う際にドメインを取得せずにIPアドレスでアクセスする形式で利用していたのですが、このIPアドレスを変更した際にWordPressが正常に動作しない状態に遭遇しました。
上記記事にも書いたのですが、WordPressではサイトURLをDBに保存しており、このURLが変更になってしまった場合、このDBの値を変更しない限り正しく動作しない状態に陥るようです。

解決策として wp_options テーブル中の 'siteurl'、及び、'home' の値を変更する旨記載してあるWebページを見つけたのですが、これでは完全に解決しなかった、且つ、より適切と思われる方法があったので、これに関してまとめておきます。

※バックアップを取ってから作業しましょう。

事象

問題となったテストサイトですが、EC2(AWS)上で動作していました。
一応 ElasticIP 割り当てて固定IPにしていたのですが、テスト期間が終了したためインスタンスはシャットダウン。
ElasticIP は利用していない場合でもコストが発生するためリリースしました。
※テスト期間終了後はシャットダウンするという話になっていた ( 調整済み )。

が、暫くして「復旧しろ」とのお達し。

インスタンス自体は残していたので再起動した ( ElasticIPアサインしてない場合、EC2は再起動で Public IP が変更になる ) のですが、

  • サイトが正しく表示されない
  • 管理画面にログインできない

といった状態に。
軽く調べてみると、結構よくある話のようです。

※旧IPにリダイレクトするっぽい。
※復旧しなければならないのであればElasticIPはリリースしない方が楽。
※テスト用でも、可能であればドメイン取得/設定 ( testserv1.hogohoge.co.jp とかでいいので ) しといた方が良いと思う。取得予定or仮のドメイン名でhosts設定しとくとかでも。

解決策1(非推奨)

「WordPress IPアドレス 変更」 辺りでググると同様の事象に遭遇したと思われる方による解決策が。

"はじめに" にも書いた
wp_options テーブル中の 'siteurl'、及び、'home' の値を変更する方法です。

個人的には非推奨です。

手順

  1. mysql にログインします。
    $ mysql -u root -p
    
  2. WordPress の DB に接続します。

    ※wordpress ( DB名 ) 部分は環境に併せて適宜変更する

    mysql> use wordpress
    
  3. wp_options テーブルの以下の値を確認します。

    ※インストール時に指定したテーブルのプレフィックスによっては別のテーブル名の場合もある。

    option_nameoption_value
    siteurlサイトURL
    homeホームページのURL

    実際の確認方法は以下
    'home' に関しては、where句を option_name = 'home' として確認すればOK

    mysql> select * from wp_options where option_name = 'siteurl';
    +-----------+-------------+-----------------------+----------+
    | option_id | option_name | option_value          | autoload |
    +-----------+-------------+-----------------------+----------+
    |         1 | siteurl     | http://52.193.34.125  | yes      |
    +-----------+-------------+-----------------------+----------+
    1 row in set (0.00 sec)
    

    通常は 'siteurl' も 'home' も同じ option_value になっていると思われます。

  4. 上記古い設定値を新しい値に更新します。
    '新しいURL' 部分を新たなIP(やドメイン)にする。例えば 'http://55.44.33.22' とか
  5. mysql> update wp_options set option_value = '新しいURL' where option_name = 'siteurl';
    
  6. update 後は再度上記の select 文で option_value の設定が更新された事を確認。

問題点

この手順で問題ない場合もあるのでしょうが、私が設定したテストサイトでは十分ではありませんでした。

WordPressの投稿データが格納される wp_posts テーブル中にも 旧IPアドレスが含まれたリンクが大量に残ってしまったためです。
画像をアップロードしたものを投稿に張り付けた場合、サイトアドレスを含む形でリンクURLが記録されているようでした。

例 : <img src="http://52.193.34.125/wp-content/uploads/top.jpg" ...

wp_posts テーブルに関しても 旧URLを一括置換すれば変換可能ですが、オペミスしてデータを壊すと言った可能性もあります。

※実はWordPressインストール直後にIP変更を行う事態になった事があり、この場合にはこの手順で問題なかった。→まだコンテンツが何も作られていなかったため。

解決策2(推奨)

最終的に実施したのはこちらの方法

wp-cli

wp-cli を使います。

※詳細に関しては Command line interface for WordPress | WP-CLI を参照

wp-cli インストール

wp-cli サイトのまんまですがインストール方法は以下
システム要件がありますが WordPress が動作しているホストなら問題なく動くと思われます。

  1. wp-cli の取得
    $ curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar
    
  2. 動作確認
    $ php wp-cli.phar --info
    NAME
    
      wp
    
    DESCRIPTION
    
      Manage WordPress through the command-line.
    
    SYNOPSIS
    
      wp 
    
    SUBCOMMANDS
    
      cache               Manage the object cache.
     ... 以下略 ...
    
  3. 実行権限の付与
    $ chmod +x wp-cli.phar
    
  4. パスが通っている場所に移動
    $ sudo mv wp-cli.phar /usr/local/bin/wp
    
  5. 実行確認
    $ wp --info
    

アップグレード時も上記と同じ方法で行えます。

wp-cli を利用したサイトURLの書き換え

wp-cli の search-replace サブコマンドを利用します。

書式は以下

$ wp search-replace '旧url' '新url' --path=WodPressのインストールパス --skip-columns=guid

以下は具体例

$ wp search-replace 'http://52.193.34.125' 'http://52.68.209.174' --path=/usr/share/nginx/html/wordpress --skip-columns=guid

実行すると以下のような以下のような出力がなされます。

+------------------+-----------------------+--------------+------+
| Table            | Column                | Replacements | Type |
+------------------+-----------------------+--------------+------+
| wp_commentmeta   | meta_key              | 0            | SQL  |
| wp_commentmeta   | meta_value            | 0            | SQL  |
| wp_comments      | comment_author        | 0            | SQL  |
| wp_comments      | comment_author_email  | 0            | SQL  |
| wp_comments      | comment_author_url    | 0            | SQL  |
| wp_comments      | comment_author_IP     | 0            | SQL  |
| wp_comments      | comment_content       | 0            | SQL  |
| wp_comments      | comment_approved      | 0            | SQL  |
| wp_comments      | comment_agent         | 0            | SQL  |
| wp_comments      | comment_type          | 0            | SQL  |
| wp_links         | link_url              | 0            | SQL  |
| wp_links         | link_name             | 0            | SQL  |
| wp_links         | link_image            | 0            | SQL  |
| wp_links         | link_target           | 0            | SQL  |
| wp_links         | link_description      | 0            | SQL  |
| wp_links         | link_visible          | 0            | SQL  |
| wp_links         | link_rel              | 0            | SQL  |
| wp_links         | link_notes            | 0            | SQL  |
| wp_links         | link_rss              | 0            | SQL  |
| wp_options       | option_name           | 0            | SQL  |
| wp_options       | option_value          | 4            | PHP  |
| wp_options       | autoload              | 0            | SQL  |
| wp_postmeta      | meta_key              | 0            | SQL  |
| wp_postmeta      | meta_value            | 0            | PHP  |
| wp_posts         | post_content          | 544          | SQL  |
| wp_posts         | post_title            | 0            | SQL  |
| wp_posts         | post_excerpt          | 0            | SQL  |
| wp_posts         | post_status           | 0            | SQL  |
| wp_posts         | comment_status        | 0            | SQL  |
| wp_posts         | ping_status           | 0            | SQL  |
| wp_posts         | post_password         | 0            | SQL  |
| wp_posts         | post_name             | 0            | SQL  |
| wp_posts         | to_ping               | 0            | SQL  |
| wp_posts         | pinged                | 0            | SQL  |
| wp_posts         | post_content_filtered | 0            | SQL  |
| wp_posts         | post_type             | 0            | SQL  |
| wp_posts         | post_mime_type        | 0            | SQL  |
| wp_term_taxonomy | taxonomy              | 0            | SQL  |
| wp_term_taxonomy | description           | 0            | SQL  |
| wp_termmeta      | meta_key              | 0            | SQL  |
| wp_termmeta      | meta_value            | 0            | SQL  |
| wp_terms         | name                  | 0            | SQL  |
| wp_terms         | slug                  | 0            | SQL  |
| wp_usermeta      | meta_key              | 0            | SQL  |
| wp_usermeta      | meta_value            | 0            | PHP  |
| wp_users         | user_login            | 0            | SQL  |
| wp_users         | user_nicename         | 0            | SQL  |
| wp_users         | user_email            | 0            | SQL  |
| wp_users         | user_url              | 0            | SQL  |
| wp_users         | user_activation_key   | 0            | SQL  |
| wp_users         | display_name          | 0            | SQL  |
+------------------+-----------------------+--------------+------+
Success: Made 548 replacements.

wp_options、及び、wp_posts で計548の置換処理が行われた事が判ります。

データ置換後サイトの表示、管理画面へのログインが行われる事が確認できました。

ファイル中の文字列置換

wp-cli を利用する事で DBに格納されたurlの一括置換は行えますが、ファイル中にurlが含まれている場合には対応できません。

きちんとした作りになっていれば、ファイルには自身のホストアドレス等は含まれない形になっているのではないかと思われます。

※img src="http://xx.xx.xx.xx/wp-contents/..." 形式ではなく、"img sc="/wp-contents/..." といったホスト名を含まない形、あるいは、相対パスの記述になっている方が望ましい。
こうしておかないと、http / https 両対応のサイトで問題がでる可能性もある。

とはいえ、「そうなってないんだから仕方ない」場合もあるかと。

調査

先ずは旧IPアドレス、ドメインでの指定が含まれるか確認しましょう。
WordPressのインストールディレクトリ以下に移動し以下で確認できると思います。

※'.' (ドット) はエスケープしてます。

$ cd /usr/share/nginx/html/wordpress
$ grep "52\.193\.34\.125" * -r

マッチングする文字列が存在すれば表示されます。該当ファイル、及び、内容によって対応が必要か確認しましょう。

対応

sed -i コマンドを利用して置換します。

書式は以下

$ sed -i "s/置換元文字列/置換先文字列/g" ファイル名

以下は具体例

$ sed -i "s/52\.193\.34\.125/52\.68\.209\.174/g" hoge.html

複数ファイルを一括置換する場合

以下で行けると思います。
find で検索したファイルを xargs コマンド使って sed の引数として渡しています。

$ find . -name ファイル名 | xargs sed -i "s/置換元文字列/置換先文字列/g"

以下具体例
( カレントディレクトリ (.) 以下の 拡張子html (*.html) のファイルを一括置換する場合 )

$ find . -name *.html | xargs sed -i "s/52\.193\.34\.125/52\.68\.209\.174/g"

最初は変換対象のファイル/ディレクトリをコピーして、それに対して実施するのをお勧め

まとめ

今回 wp-cli を利用した方法に関して書きましたが、wp-cli 便利です。

設定の確認

たとえば、解決策1で実施した siteurl や home の値確認等も

$ wp option get siteurl
$ wp option get home

といったコマンドで取得可能ですし、

管理/運用系作業

MySQLデータの最適化なんかも可能です。

$ wp db optimize

DBやコンテンツデータのエクスポート/インポート等も可能で、利用する事でWordPressの管理作業が省力化/自動化できる可能性は高いと思われます。

user サブコマンドで ユーザ管理も行えます。

WordPressの構成

plugin サブコマンドでプラグインをインストール/アンインストールしたり、menu や sidebar 等のコマンドでこれらアイテムの管理が行えるので、サイトを(反)自動構成すると言った使い方も可能かと思われます。

WordPress 使いで wp-cli を利用した事がないのであれば利用してみてはいかがでしょうか。