WordPressのサーバー間同期ツールのwordmoveですが、長いことお世話になっているものの、しばらくテンプレートしか同期していませんでした。
が、数日後に運用中のサイトで価格をすべて変更するSQLを流し込むのにローカルテストをしたかったので、DBの同期を試してみましたが、予想はしてたものの、ぜんぜんうまく出来ませんでした。その原因調査した報告です。
まずは初めのエラー。
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'
つまり、ssh接続でコマンド実行に失敗している模様。
wordmoveのmovefile.ymlによると、configファイルを利用する場合、hostnameの接続のみで操作できるようになるそうです。
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されたファイルの1行目をみると、こんな行が出ています。
/*!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に最近追加されたセキュリティ対策でした。
2024年5月17日! まだ一月も経ってない。
解決策もいくつかある
推奨:
変更が行われたバージョンの MariaDB Server から、セキュア クライアントを使用してダンプをインポートします。
バックアップを取得するには、mariadb-dump の古い (安全でない) バージョンを使用します。
バックアップ時に のような行を削除します
mariadb-dump|tail +2
。インポート時に次のような行を削除します
tail +2|mariadb
wordmoveはコマンドフックも用意されていますが、importのコマンドを加工しないと駄目なようです。
wordmoveで操作している部分の話なので、前後のコマンドで操作ができない、、、どうすれば、、、
いっそ、wordmoveを変えるか、、、ということでgitのwordmoveのレポジトリをフォークし、ローカルに配置します。
/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でローカルとリモート環境用を区別できるようにすこし加工します。
class << self
def deployer_for(cli_options)
options = movefile.fetch.merge! cli_options #追加
environment = movefile.environment(cli_options) #追加
おなじファイル内でインポートする際の挙動をローカルとリモートで変更します。
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を利用して登録します。
# 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を見ると、インポートされてるけど、パスが変わってない!
というわけで今一度wordmoveをよく見ていく。パスを変換している部分。lib>sql_adapter>wpcli.rbだ。
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のパラメータが参照している箇所がある。
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をつけてみると
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'
エラー無しで完了した!けど、パスが変わってない!!!
ということで、一度パスを直接指定してみる。おや?
.envが間違ってた。あれほど最後にスラッシュつけちゃ駄目だって言われてたのに。
いったんリビルドする。設定も追加。
ようやくできたー。
振り返ってみて
長年何気なく使ってきたツールですが、初めて内部を触ってみたところ、構造がわかりやすく、手直しもしやすかったので助かりました。
ただ、Rubyやってないんですよ私。これを機会にもう少し勉強してみたいと思います。
mysqlとMariaDB、このほかバージョンなどでwordmoveのデータベース操作は厳しそうな感じがします。マルチサイトも対応していないので、今後も継続して使うのは難しいかも知れませんね。もしなにか良い方法などご存知でしたらぜひ教えていただけると幸いです。
こちらの記事で、実際にConohaVPSのKUSANAGI同期させるまでの手順をご紹介いたしました。
今回作成したレポジトリはこちらに。ご興味があれば。
以上ご報告でした。ありがとうございました。