タグ別アーカイブ: cron

wordpressでリモートにある環境にデータベースを転送したい

はめじに

wordpressでリモートにある環境にデータベースを転送したい。転送というか同期というか。

通常の環境であれば管理者メニューからエクスポート > インポートとすればすむ話なのだけれど、今回はちょっと変わった事情があった。

その条件ってのは下記の通り

  • 手元のサーバにあるワードプレスのデータベースの一部(コメントとかは上書きしないようにする)をリモートサーバに転送したい
  • リモートサーバにはsshでログイン可能
  • テータベースの一部のうち、post_metaにあるmeta_keyがviewsは上書きしたくない
  • 転送するのは一日に一回ぐらいのそこそこのペースで転送したい

リモートホストにsshでログインできるのでsshとパイプを使ったワンライナーでやってしまおう的な。

またpost_metaのテーブルはちょっとやっかい。今回利用しているプラグインでWP-PostViewsという閲覧数を保管するプラグインがある。これは閲覧数をpost_metaにmeta_key = viewsで管理している。だからそこをハズしたい。

キャプチャ4

というわけでさっくり


mysqldump –h localdbhost –u localuser –plocaldbpassword  --add-drop-table wpdbname wp_options wp_posts wp_postmeta wp_term_relationships wp_term_taxonomy wp_terms wp_users wp_usermeta | ssh remotesshuser@remotehost.example.com mysql -f -h remotedbhost -u remotedbuser –premotedbpassword  remotewpdb

これでひとまずpost_meta以外はいけた。

データがちょっと複雑なpost_meta

post_metaに関してはmysqldumpにwhere句が使えるらしいので使ってみる。

次にpost_metaをうまく通してやるためにオプションを調整してやる。


mysqldump –h localdbhost –u localuser –plocaldbpassword   --add-drop-table=false --extended-insert=false --where="meta_key!='views'" mysqldump –h localdbhost –u localuser –plocaldbpassword wp_postmeta  |  ssh remotesshuser@remotehost.example.com mysql -f -h remotedbhost -u remotedbuser –premotedbpassword remotewpdb

キャプチャ

--add-drop-table=false

これは対象テーブルのdrop table – if exists文を出力に含めないようにするためのオプション。

基本的にはテーブルがあるっていう前提なのでcreate-infoごといらないかもしれない。(create文ごとなくすには—no-create-infoを付けるといい)

今回は安全に動作(運用)するために付けておくことにする。ここで与えたオプションはlong形式の—add-drop-tableなんだけど、実は引数でtrue falseが与えられるらしい。よくありがちなのは—no-add-drop-tableみたいに対応してる気がしてたんだけどそうじゃないみたい。

公式には書いてないので気がつかなかった。っていうか引数ありって本当意外。

  • --add-drop-table

DROP TABLEステートメントをCREATE TABLEステートメントの前に追加します。
MySQL ::   MySQL 5.1 リファレンスマニュアル :: 7.12 mysqldump — データベースバックアッププログラム

--where=”meta_key!=’views'”

これはmeta_keyで上書きしたくない条件を指定。今回は手元のデータのうち閲覧数は上書きしたくなかった。sqlだったらすんなりwhere句書いちゃえば楽なのになーって思ったらmysqldumpでもwhereが書けるらしい。

  • --where='where_condition', -w 'where_condition'

あるWHERE状態に選択された行のみダンプします。ユーザのコマンドインタープリタにとって特別なキャラクタ、もしくはスペースを含んでいる場合、状態の周りをクオートで囲まなければいけません。

MySQL :: MySQL 5.1 リファレンスマニュアル :: 7.12 mysqldump — データベースバックアッププログラム

–extended-insert=false

キャプチャ2

このオプションも引数を取るらしい。このオプションは

  • --extended-insert, -e

複数のVALUESリストを含む、複数行INSERT構文を使用してください。これにより、ダンプファイルサイズを小さくし、ファイルが再ロードされる際の挿入スピードがあがります。

MySQL :: MySQL 5.1 リファレンスマニュアル :: 7.12 mysqldump — データベースバックアッププログラム

となっている。いわゆるbulk insertとかmultiple-row insertsとか言われてるあれにするようなやつですね。


insert hoge (id, hoge) values (1, hoge), (2, hoge1), (3, hoge), (4, hoge);

で、コレって結構早くする上では重要なものなのです。このオプションがonでないと、bulk insertが有効になっていないと、かなり遅くなります。なのですが後述するmysql -fと組み合わさって今回の運用上はoffにしてないとうまく目的を達成できません。

今回の運用上、というところはどういったところなのか。

さっきの例だとid, hogeという二つのカラムに対して四つの行を一つのinsert文でinsertしようとしてる。で、カラムの名前から分かるように、idというのはpkeyなのでunique制約がある。となるとき、上のinsertだとduplicateでinsertできないことがある。もともとid=1な行があるときとか。で、そういうのは無視しながら必要な行だけをinsertしたいので、これらのinsert文を分けて書く必要がある。なのでこのオプションを有効にしてやる。するとこんな感じのinsert文になる。


insert hoge (id, hoge) values (1, hoge);

insert hoge (id, hoge) values (2, hoge1);

insert hoge (id, hoge) values  (3, hoge);

insert hoge (id, hoge) values (4, hoge);

これでid=1は通らなくても他のinsert文は通ってくれるので期待通りの結果になるかな!

mysql –f

受け側のオプション。エラーがあっても処理を続行する。先のcreate文ですでにtableが存在しても続けたり、insert文でduplicateな行だったとしても続けてくれる。おかげさまでイケるようになります。

おわりに

これでcronに入れとけばテキトウに同期してくれそう。sshでパスワードのプロンプトをなくすために公開鍵をやりとりする、とかやる必要はあるけれど。

でもこれできっと便利。しらばらくは手でやってみるけど。

転送量に制限をかけてバックアップをとりたい

1. 転送量多いとISPから怒られちゃうよ!

現在、インターネットを通じてファイルのバックアップを行っている。夜中などのトラフィックが比較的すいている時間帯を選んでバックアップを行っている。

バックアップの内容はいろいろなもので、そしてそこそこ大きい。バックアップするデータ量は日によってまちまち。で、このバックアップデータが結構でかいので、バックアップにちょっと頭を悩ませている。というのも、利用しているISPが一日の転送量に制限をかけているからだ。

制限といっても一定量に達したら自動的に帯域を絞る、というものではなく、なんと警告メールがくる。あなた帯域使いすぎですよ、って。正直怖いッス。

で、なにかよいバックアップ方法がないだろうかと考えてみた。

まず、バックアップの特性について考える。

  • バックアップデータは大きい。結構大きい。数GB単位。
  • ファイルは分割されている。一つのファイルはおおよそ数MB ~ 1GB。
  • 転送量は一日ごとに上限値が決まっている。そしてそれはユーザが意識して制限量以下に抑える必要がある。
  • 転送量制限が一日ごとなので一日ごとにバックアップをとりたい
  • バックアップしたいデータ、例えば1日目に1日目の増分の50%、二日目には一日目の増分の残り50%と二日目の増分100%、のように、遅れてバックアップを取っても良い。ただし増分が一日の転送量を超えてしまうと終わりなきキューになるのでダメだけれどね。

上記の条件の内、とくに一日目、二日目という風にバックアップを分けてもよい、という条件があるので、コレを利用したrsyncを使ったバックアップ方法を考えてみた。

続きを読む 転送量に制限をかけてバックアップをとりたい

FreeBSDでcronにdateコマンドを含めたかったけどうまくいかない

1. はじめに

FreeBSD8.2-R amd64でcronにdateコマンドを含めたかったけどうまくいかない。
cronにdateコマンドを絡めた作業をさせたかった。具体的にはtarコマンドを用いてファイルのバックアップをとらせたかった。
このときファイル名にdateコマンドを用いて日付情報を付加しようと思った。でもうまく行かない。

とりあえず最初は思いついたとおりのコマンド、dateをバッククォートで囲んでそれを引数にtarをさせた。以下はバッククォートを利用したdateコマンドの例。

shell> grep date /etc/crontab
*       *       *       *       *       yousan  mail -s ` date '+%Y' ` mail@localhost < hoge

上記のように書いたのだけれどうまく動かない。エラーログから察するに、 ‘mail -s `date’までは実行されている様子。
でもその後が続かない。

2. 意外にも解決方法がすぐにでてきたけれど。。。

さっくりググったら同じような症状がいっぱい出てきた。日本語の情報も数多くある。cron, dateというのはよくよく知られた問題のようだ。
標準のやり方ではうまく行かないみたい。またその対処方法も広く知られているらしい。
なんとwikipediaにまで対処方法が記載されていた。

よくあるミス

よくあるミスのひとつは、コマンド指定においてエスケープせずに「%」記号を使うことで、これはエスケープする必要がある。

# ミス:
1 2 3 4 5 touch ~/error_`date "+%Y%m%d"`.txt

この場合、デーモンからは以下のようなエラーメッセージがメール送信される:「/bin/sh: unexpected EOF while looking for `」

# エスケープしたもの:
1 2 3 4 5 touch ~/right_$(date +\%Y\%m\%d).txt
# 以下でも動作可能: シングルクオート
1 2 3 4 5 touch ~/error_$(date '+%Y%m%d').txt
# ダブルエスケープ版。以下のようなファイル名になる: ~/error_\2006\04\03.txt
1 2 3 4 5 touch ~/error_$(date '+\%Y\%m\%d').txt

crontab – Wikipedia

どうやらバッククォートの代わりに$を利用するといいらしい。
さっそくやってみた

3. $を使えばcronでdateがうまくいくはずが。。。

動かない。動かない。FreeBSDで$を使ってもコマンドに置換されない。
さっきの例だと変なメールが送られてくる。

下記はcrontabの記述

shell> grep mail /etc/crontab
* * * * * yousan  mail -s $(date '+%Y') hoge@localhost < ~yousan/tmp/hoge

送られてきたメール

From: ohoge@localhost
To: hoge@localhost
 Subject: Cron <cron@localhost&gt; mail -s $(date '+
X-Cron-Env: <SHELL=/bin/sh>
 X-Cron-Env: <PATH=/etc:/bin:/sbin:/usr/bin:/usr/sbin>
 X-Cron-Env: <MAILTO=hoge@localhost>
 X-Cron-Env: <HOME=/home/yousan>
X-Cron-Env: <LOGNAME=yousan>
X-Cron-Env: <USER=yousan>

Syntax error: Unterminated quoted string
 Syntax error: Error in command substitution

wikipediaとかその他諸々にあるような書き方をしてみたんだけれど動かない。FreeBSDは違うのかなぁ・・・、とか思っていろいろやってたらうまくいった。どうやらシングルクォートで括っても%はエスケープされない?(する必要がある?)ようだ。

下記の通りにするとうまくいった。

shell> grep mail /etc/crontab
 * * * * * yousan  mail -s $(date +\%Y) hoge@localhost < ~yousan/tmp/hoge

これでバックアップが全てちゃんととれるはず!

4. まとめ

FreeBSDのcrontabでdateコマンドなど、パーセントが含まれるコマンドを実行したいときには、シングルクォートで囲むだけではなくちゃんとバックスラッシュでクォートしてやる必要がある。