wordmoveのDB同期を動かすまで

WordPressのサーバー間同期ツールのwordmoveですが、長いことお世話になっているものの、しばらくテンプレートしか同期していませんでした。

が、数日後に運用中のサイトで価格をすべて変更するSQLを流し込むのにローカルテストをしたかったので、DBの同期を試してみましたが、予想はしてたものの、ぜんぜんうまく出来ませんでした。その原因調査した報告です。

まずは初めのエラー。

![Cursor_と_movefile_yml_—_local-site3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38388/164cebf7-c9a1-dd9d-5bca-99cdc66d0546.png)

```
OpenSSH keys only supported if ED25519 is available
```

wordmoveを動かしているコンテナ内のOpenSSHでは　Githubの公式でもキーの生成に案内されているED25519が使えないとのこと。
ED25519で暗号化された認証鍵は次のgemsを入れてねとあるので、gemをインストールします。

```
gem install ed25519 -v "~> 1.2"
gem install bcrypt_pbkdf -v "~> 1.0"
```

インストールできたので、もう一度

```
wordmove pull --all

mysqldump: Got error: 1130: "Host '******.rmt4.static.cnode.jp' is not allowed to connect to this MariaDB server" when trying to connect (Wordmove::ShellCommandError)
```

次はリモートサーバー側でMariaDBに接続できないとアラートが出ているようです。

リモートにログインしてみるとmysqldumpを実行した形跡（空のdump.sqlがあった）があり、ローカルコンテナからsshコマンド経由で利用すると、mysqldumpも使えることが判明します。

```
ssh my-site 'mysqldump -u mysite_db -******* mysite_db > /home/kusanagi/mysite/DocumentRoot/wp-content/dump.sql'
```

![Cursor_と_root_vm-d56d7c46-2b__home_kusanagi_mysite_DocumentRoot_wp-content_と_movefile_yml_—_local-site3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38388/bcf4464d-6b03-6b6c-3e23-61c36b789bc4.png)

つまり、ssh接続でコマンド実行に失敗している模様。

wordmoveのmovefile.ymlによると、configファイルを利用する場合、hostnameの接続のみで操作できるようになるそうです。

https://github.com/welaika/wordmove/wiki/movefile.yml-configurations-explained

>Please note that the only mandatory key is host, because you can configure SSH connections in ~/.ssh/config, thus using the specified host will call in all the options expressed there. For example, having a ~/.ssh/config with

```
Host client_X_staging
  Hostname 79.99.8.94
  User welaika
  Port 1337
  ProxyCommand ssh code -W %h:%p
```
>you can fill `movefile.yml` just like this
```
staging:
  ssh:
    host: client_X_staging
```

movefile.ymlのssh設定を/ssh/configファイルで使用したホスト設定のエイリアス名に変更します。

```
  ssh:
    host: my-site
    # host: "<%= ENV['STAGING_SSH_HOST'] %>"
    # user: "<%= ENV['STAGING_SSH_USER'] %>"
    # password: password # password is optional, will use public keys if available.
    # port: <%= ENV['STAGING_SSH_PORT'] %> # Port is optional
    # rsync_options: '--verbose --rsync-path="sudo /usr/bin/rsync"' # Additional rsync options, optional
```

さあもう一度トライ（リモートサーバー側のdump.sqlは手動で消す）

結果が変わらなかったので、.envのデータベースホスト設定がSSHのIPアドレスを指定しており、SSH越しのDBなのでlocalhostを見るように修正する。

```
STAGING_DB_HOST=localhost
```

```
wordmove pull --all -e staging

    local | mysql --host=[secret] --user=[secret] --password=[secret] --database=[secret] --execute="SET autocommit=0;SOURCE [secret]/wp-content/dump.sql;COMMIT"
ERROR at line 1 in file: '/html/wp-content/dump.sql': Unknown command '\-'.
```
ようやくローカルにdump.sqlが登場しましたが、なにやらimportできないとエラーになっています。
「Unknown command `'\-'.`」ときました。
dumpされたファイルの１行目をみると、こんな行が出ています。
```
/*!999999\- enable the sandbox mode */ 
-- MariaDB dump 10.19  Distrib 10.6.18-MariaDB, for Linux (x86_64)
--
-- Host: localhost    Database: mysite_db
-- ------------------------------------------------------
-- Server version	10.6.18-MariaDB-log
```

こんなのあったかなと、いろいろと探してみると、MariaDBに最近追加されたセキュリティ対策でした。

https://mariadb.org/mariadb-dump-file-compatibility-change/

2024年5月17日!　まだ一月も経ってない。

解決策もいくつかある

> - **推奨:**
>     
>     変更が行われたバージョンの MariaDB Server から、セキュア クライアントを使用してダンプをインポートします。
>     
> - バックアップを取得するには、mariadb-dump の古い (安全でない) バージョンを使用します。
> - バックアップ時に のような行を削除します`mariadb-dump|tail +2`。
> - インポート時に次のような行を削除します`tail +2|mariadb`

wordmoveはコマンドフックも用意されていますが、importのコマンドを加工しないと駄目なようです。

wordmoveで操作している部分の話なので、前後のコマンドで操作ができない、、、どうすれば、、、

いっそ、wordmoveを変えるか、、、ということでgitのwordmoveのレポジトリをフォークし、ローカルに配置します。

![Cursor_と_welaika_wordmove__Multi-stage_command_line_deploy_mirroring_and_task_runner_for_Wordpress.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38388/c18cbd8f-9a10-1097-c8f3-b2c16e531d46.png)


/wordmoveフォルダへクローン
```
git clone git@github.com:murodon/wordmove_custom.git
```
いったんコンテナ内の古いwormoveを削除します。

```
gem uninstall wordmove
Remove executables:
        wordmove

in addition to the gem? [Yn]  y
Removing wordmove
Successfully uninstalled wordmove-5.2.1
```

wordmoveのlib>deployer>base.rbでローカルとリモート環境用を区別できるようにすこし加工します。

```ruby
      class << self
        def deployer_for(cli_options)


          options = movefile.fetch.merge! cli_options　#追加
          environment = movefile.environment(cli_options)　#追加

```

おなじファイル内でインポートする際の挙動をローカルとリモートで変更します。

```ruby
      def mysql_import_command(dump_path, options)
        if options[:origin] == 'local'
          # ファイルの最初の行を読み取る
          first_line = File.open(dump_path, &:readline).strip

          # コマンドを構築
          if first_line == '/*!999999\\- enable the sandbox mode */'
            command = ["tail -n +2 #{Shellwords.escape(dump_path)} | mysql"]
          else
            command = ["mysql"]
          end
        else
          command = ["mysql"]
        end
        command << "--host=#{Shellwords.escape(options[:host])}" if options[:host].present?
        command << "--port=#{Shellwords.escape(options[:port])}" if options[:port].present?
        command << "--user=#{Shellwords.escape(options[:user])}" if options[:user].present?
        if options[:password].present?
          command << "--password=#{Shellwords.escape(options[:password])}"
        end
        command << "--database=#{Shellwords.escape(options[:name])}"
        command << Shellwords.split(options[:mysql_options]) if options[:mysql_options].present?

        # 通常のコマンド実行時のみ --execute オプションを追加
        unless first_line == '/*!999999\\- enable the sandbox mode */'
          command << "--execute=\"SET autocommit=0; SOURCE #{Shellwords.escape(dump_path)}; COMMIT\""
        end
        command.join(" ")
      end
```

一度コミットして、リポジトリに上げたものを、今度はコンテナ内でspecific_installを利用して登録します。

```bash
# gitから直接gemをインストールする
gem install specific_install
gem specific_install https://github.com/murodon/wordmove_custom.git
wordmove -v
5.2.2
```
登録されました。ではもう一度

```
wordmove pull --all
local | mysql --host=[secret] --user=[secret] --password=[secret] --database=[secret] < [secret]/wp-content/dump.sql.tmp

    local | adapt dump for vhost
Error: YIKES!
省略
unexpected token at '' (JSON::ParserError)
```

さて、、、ここまで来て、、、、

しかもDBを見ると、インポートされてるけど、パスが変わってない！

![Cursor_と__MySQL_5_5_5-10_6_4-MariaDB-1_10_6_4_maria_focal__local-wp_proto_wordpress_wp_options.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38388/691fb7eb-8d54-be06-7725-54163e0c1ed8.png)

というわけで今一度wordmoveをよく見ていく。パスを変換している部分。lib>sql_adapter>wpcli.rbだ。

```ruby
def command
  unless wp_in_path?
    raise UnmetPeerDependencyError, "WP-CLI is not installed or not in your $PATH"
  end

  opts = [
    "--path=#{cli_config_path}",
    from,
    to,
    "--quiet",
    "--skip-columns=guid",
    "--all-tables",
    "--allow-root"
  ]

  "wp search-replace #{opts.join(' ')}"
end
```

どうやらこのcli_config_pathがうまく機能していないらしい。後ろの方を眺めると、wp-cli.ymlファイルやwp cliのパラメータが参照している箇所がある。

```ruby
      def load_from_cli
        cli_config = JSON.parse(`wp cli param-dump --with-values`, symbolize_names: true)
        cli_config.dig(:path, :current)
      end
  ```

—allow-rootをつけろ！と怒っていたのでここに—allow-rootをつけてみると

```ruby
      def load_from_cli
        cli_config = JSON.parse(`wp cli param-dump --allow-root --with-values`, symbolize_names: true)
        cli_config.dig(:path, :current)
      end
```


```
    local | gzip -d -f "[secret]/wp-content/dump.sql.gz"

    local | mysql --host=[secret] --user=[secret] --password=[secret] --database=[secret] < [secret]/wp-content/dump.sql.tmp

    local | adapt dump for vhost

    local | wp search-replace --path=[secret] [secret] [secret] --quiet --skip-columns=guid --all-tables --allow-root

    local | adapt dump for [secret]_path

    local | wp search-replace --path=[secret] [secret]/ [secret] --quiet --skip-columns=guid --all-tables --allow-root

    local | delete: '[secret]/wp-content/dump.sql'
```

エラー無しで完了した！けど、パスが変わってない！！！

ということで、一度パスを直接指定してみる。おや？


![Cursor_と__env_—_local-site3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38388/84b81c90-edf6-3f3d-ff67-9e350090a147.png)


.envが間違ってた。あれほど最後にスラッシュつけちゃ駄目だって言われてたのに。

いったんリビルドする。設定も追加。

![_MySQL_5_5_5-10_6_4-MariaDB-1_10_6_4_maria_focal__local-wp_proto_wordpress_wp_options.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38388/925c62ce-c626-a685-0772-f7114de343ac.png)

ようやくできたー。

# 振り返ってみて

長年何気なく使ってきたツールですが、初めて内部を触ってみたところ、構造がわかりやすく、手直しもしやすかったので助かりました。

https://github.com/welaika/wordmove/blob/master/CONTRIBUTING.md

ただ、Rubyやってないんですよ私。これを機会にもう少し勉強してみたいと思います。

mysqlとMariaDB、このほかバージョンなどでwordmoveのデータベース操作は厳しそうな感じがします。マルチサイトも対応していないので、今後も継続して使うのは難しいかも知れませんね。もしなにか良い方法などご存知でしたらぜひ教えていただけると幸いです。

こちらの記事で、実際にConohaVPSのKUSANAGI同期させるまでの手順をご紹介いたしました。

https://qiita.com/murodon/items/6dccfc9f92544dc01e04


今回作成したレポジトリはこちらに。ご興味があれば。

https://github.com/murodon/wordmove_custom




以上ご報告でした。ありがとうございました。