svnsyncを使ってリポジトリレプリケーション

バックアップとして、もしくはバックアップからの復旧時間が嫌な場合は、リポジトリのミラーリングとしてsvnsyncがSVN1.4から使えるようになっている。

今回はsvnsyncの動作を確認してみる。
環境はWindows Vista、SVN1.5.3。
本当はリモートのリポジトリにミラーリングしたいんだけど、ローカルApacheで我慢。

Apacheは↓みたいな設定でURLを別にしている。SVNのBasic認証もかけてみた。

 <Location /svn>
DAV svn
SVNListParentPath on
SVNParentPath C:\fujihara\svn_root
AuthType Basic
AuthName "Subversion Basic Auth"
AuthUserFile C:\fujihara\svn_root\passwd
Require valid-user
</Location>
<Location /svnmirror>
DAV svn
SVNListParentPath on
SVNParentPath C:\fujihara\svn_mirror
AuthType Basic
AuthName "Subversion Basic Auth"
AuthUserFile C:\fujihara\svn_root\passwd
Require valid-user
</Location>

「http://localhost:8888/svn/repo01」と「http://localhost:8888/svnmirror/repo01m」を同期させる。

ミラー側のリポジトリ設定

まずはミラー先のリポジトリを作成する。

mkdir c:\fujihara\svn_mirror
cd c:\fujihara\svn_mirror
svnadmin create repo01m

次に「C:\fujihara\svn_mirror\repo01m\hooks」にある「pre-revprop-change.tmpl」を「pre-revprop-change.bat」、「start-commit.tmpl」を「start-commit.bat」にリネーム。Windowsの場合はbatでUnixだとtmpl拡張子を削除かshとかでもいいかも。
バッチファイルの中身を以下に修正。

 // pre-revprop-change.bat
if "%3" == "svnsyncuser" exit 0
exit 1
 // start-commit.bat
if "%2" == "svnsyncuser" exit 0
exit 1

これをしないと

svnsync: Repository has not been enabled to accept revision propchanges;
ask the administrator to create a pre-revprop-change hook

と怒られる。この記述によって、svnsyncuserからしかアクセスができないようになるので、ミラー側に送られてきたコミットやリビジョンのログメッセージ変更を防ぐ。

次にミラー側のリポジトリを初期化。
ミラー側のリポジトリは空っぽでないと「svnsync: Cannot initialize a repository with content in it」と怒られるので注意。

 c:\fujihara\svn_mirror>svnsync init http://localhost:8888/svnmirror/repo01m  http://localhost:8888/svn/repo01 --non-interactive --source-username=fujihara --source-password=password --sync-username=svnsyncuser --sync-password=password
Authentication realm: Subversion Basic Auth
Username: fujihara
Password for 'fujihara': ********
Copied properties for revision 0.

svnsyncuserはsvnsync用のユーザをApacheで指定したファイル(今回はpasswd)に追加する。こればっかりは平文になりますなー。

最後にsvnsyncコマンドでレプリケーション開始。

 c:\fujihara\svn_mirror>svnsync sync file:///c:/fujihara/svn_mirror/repo01m --sync-username=svnsyncuser --sync-password=secret
Committed revision 1.
Copied properties for revision 1.
Committed revision 2.
Copied properties for revision 2.
Transmitting file data .
Committed revision 3.
Copied properties for revision 3.

これでばっちりレプリケーションができた。

ローカルでのミラーリング

ローカルのディスクにsvnsyncしてみる。svnsyncはURI?でレプリケーション先を設定できるので、リモートであろうがローカルであろうが意識しなくていい。
ローカルディスクにリポジトリを配置し、NFS上にレプリケーションを作成する・・・という構成にも可能。

 c:\fujihara\svn_mirror>svnadmin create repo01ml
c:\fujihara\svn_mirror>svnsync init file:///c:/fujihara/svn_mirror/repo01ml file:///c:/fujihara/svn_root/repo01
c:\fujihara\svn_mirror>svnsync sync file:///c:/fujihara/svn_mirror/repo01ml

リモート&リモートでもできた。

 c:\fujihara\svn_mirror>svnsync init http://localhost:8888/svnmirror/repo01mr http://localhost:8888/svn/repo01
c:\fujihara\svn_mirror>svnsync sync http://localhost:8888/svnmirror/repo01mr

マスタとなるリポジトリの設定

ミラー側では以下の設定を行う。今回はrepo01リポジトリを複製しようとしているので、「C:\fujihara\svn_root\repo01\hooks\post-commit.bat」を作成する。これはコミット後に処理されるスクリプトなので、

svnsync sync http://localhost:8888/svnmirror/repo01m --non-interactive --source-username=fujihara --source-password=password --sync-username=svnsyncuser --sync-password=password

と記述してコミット毎に同期させる。コミット毎が2回走るのに近いので、軽くするんだったらcronとかに同じ内容を書けば、まとめて同期することも可能。
source-userとsource-passwordはなくても動くので謎。マスタ側のSVNユーザを指定するのかな?
Apacheで認証かけているときはオプションをちゃんと付けないとよくわからないエラー(MERGE of ・・・ 200 OKとか)になったり、ロック状態におちいるので注意。ロック状態の解除はsvnsyncでFailed to get lock on destination repos, currently held by・・・を参照のこと。

またコミットメッセージなどのリビジョンのプロパティも同期させないとだめなので、「C:\fujihara\svn_root\repo01\hooks\post-revprop-change.bat」を作成し、

svnsync copy-revprops http://localhost:8888/svnmirror/repo01m %2 --non-interactive --source-username=fujihara --source-password=password --sync-username=svnsyncuser --sync-password=password

と記述する。

動作確認

成功。コミット毎に同期も可能だし、あとでsvnsyncコマンドをたたいてまとめて同期も可能。ミラー側のリポジトリのコミットやログ変更もはじいてくれた。すばらしー。

参考