subversion/Tips


リアルタイムにリポジトリのバックアップを取る

いろんな所で語られているようにsvnsync使えばできるんですが、単純にやるとcommitはうまくいったのにも関わらず同期を取るのがうまくいかなかった場合に、利用者にはエラーとなって返ってしまうので都合が悪いことがあります。
ここで説明するのはcommitと同期の処理を分け、利用者に同期の処理結果を隠蔽するための手順です。
また、同期自体に遅延があった場合などにも同期の終了を待たずに済みます。

ソースリポジトリ、バックアップリポジトリはそれぞれ別サーバーとし、apacheのdav_svnモジュール使ってHTTPで使います。
ソースリポジトリは既に運用中の前提とします。
それ以外の環境の場合はよろしくやって下さい。

まずはありふれた手順なので簡単にいきます。

バックアップサーバーの作業

バックアップ側のサーバーにバックアップ先リポジトリを作成します。
# mkdir /var/www/html/repos
# cd /var/www/html/repos
# svnadmin create repo

hookスクリプトをテンプレートからコピーして実行権限付けます。
# cd repo/hooks
# cp -p start-commit.tmpl start-commit
# cp -p pre-revprop-change.tmpl pre-revprop-change
# chmod 755 start-commit pre-revprop-change

start-commitを編集します。
テンプレートに謎のスクリプトが記述されているのでコメントアウトします。
commit-allower.pl --repository "$REPOS" --user "$USER" | | exit 1
special-auth-check.py --user "$USER" --auth-level 3 | | exit 1
↓
#commit-allower.pl --repository "$REPOS" --user "$USER" | | exit 1
#special-auth-check.py --user "$USER" --auth-level 3 | | exit 1
特定ユーザー以外からのcommitをしようとした場合にエラーが返るようにします。
exit 0
↓
if [ "$USER" == "admin" ]; then exit 0; fi
exit 1
バックアップ先リポジトリへの直接の変更をすると同期が取れなくなってしまうので、それを避ける措置です。
ここで指定されている"admin"ユーザーは例なので任意のユーザー名で構いません。

pre-revprop-changeを編集します。
exit 1
↓
if [ "$USER" == "admin" ]; then exit 0; fi
exit 1
よく分かりませんがsvnsyncを使う場合はこのhookスクリプトを作っておく必要があるみたいです。
割とどうでもいいので調べてません。

ここまでやったらバックアップ先リポジトリを初期化してから同期をとります。
# chwon -R apache:apache /var/www/html/repos/repo
# svnsync init http://バックアップ先/repos/repo http://バックアップ元/repos/repo --username admin --password admin
# svnsync sync http://バックアップ先/repos/repo --username admin --password admin
ちなみにアカウントとパスワードを保存すると~/.subversionあたりに収納されるみたいです。

続けてソースサーバーで作業します。

ソースサーバー側の作業

まずはsvnsyncがちゃんと動くか試しておきましょう。
# su - apache -s /bin/bash -c "svnsync sync http://バックアップ先/repos/repo --username admin --password admin --non-interactive"
これがうまくいかないようなら設定等が誤っていますので確認して下さい。
うまくいったら次にいきます。

同期用のスクリプトをこんな感じで作成します。
とりあえず/var/www/html/repos/sync.shとでもしときましょうか。
#!/bin/sh

REPOS=$1
REPO=$(basename ${REPOS})

DST_HOST="バックアップ先IP"
USER="admin"
PASS="admin"

WGET_OPTS="-O- --http-user ${USER} --http-password ${PASS}"
SYNC_OPTS="--username ${USER} --password ${PASS} --non-interactive"

wget ${WGET_OPTS} http://${DST_HOST}/repos/${REPO} > /dev/null 2>&1

if [ "$?" -eq "0" ]; then
  RESULT=1
  while [ "${RESULT}" -ne 0 ]; do
    svnsync sync http://${DST_HOST}/repos/${REPO} ${SYNC_OPTS}
    RESULT=$?
  done
fi
バックアップ先にHTTP接続できなかった場合と、svnsync自体がうまくいかなかった時の処理をさせるための物です。
このあたりを処理しておかないと無駄に待たされたりすることがあります。

そしてhookスクリプトをテンプレートからコピーします。
# cd /var/www/html/repos/repo/hooks
# cp -p post-commit.tmpl post-commit
# chmod 755 post-commit

post-commitを編集します。
(行追加)
bash /home/svn/sync.sh ${REPOS} 2>&1 &
mailer.py commit "$REPOS" "$REV" /path/to/mailer.conf
↓
#mailer.py commit "$REPOS" "$REV" /path/to/mailer.conf
bash /home/svn/sync.sh ${REPOS} 2>&1 & の処理によって、post-commitからの同期処理自体をバックグラウンドに持って行きます。
こうすることで、利用者は同期が取れているか取れていないかに関係なく、自分のcommitがうまくいったかどうかだけを気にすれば良いということになります。

同期の設定は以上です。
しかしこれだと当然実際に同期が取れているかどうかが分かりにくくなるので、そのあたりは別途同期が取れているかをチェックするための仕組みを考える必要があるでしょう。
それについてはいずれ機会があれば書こうと思います。
リクエストがあれば優先してやるかもしれません。



参考URL

  • 最終更新:2016-06-13 10:16:58

このWIKIを編集するにはパスワード入力が必要です

認証パスワード