Subversion自动备份方案

分享项目自动化Subversion by 达达 at 2011-10-20

目前的项目用的是SVN,服务器是内网的一台Windows 2003的机器,上面跑Visual SVN Server,程序、策划、美术有各自的SVN,昨天给SVN做了一下备份方案,这里分享一下。

备份分为完整备份和增量备份两步,完整备份我计划是每周运行一次增量备份每天跑一次,因为完整备份占用磁盘空间比较大,运行时间较长,比如我们目前的SVN完整备份需要3小时多,磁盘占用有几十G。

备份的原理很简单,SVN本身就提供了完整备份和增量备份的命令,但要做自动备份需要自己写脚本,因为我对Windows的批处理脚本不熟悉,于是就用PHP写备份脚本了。自动化的原理是利用svnlook获取当前SVN的最新版本号,每次完整备份或者增量备份都将版本号记录到一个文件中,下次增量备份时读取该文件再对比版本号,版本号有变动就开始从上次的版本号+1到最新版本号增量备份。理解了这个原理,你可以用你自己喜欢的脚本语言做自动备份脚本,下面是我的PHP版备份脚本:

svnbackup-full.php

<?php
$svn_base = "H:\\SVN-Repos\\";
$backup_base = "G:\\SVN-Backups\\";

$svn_list = array(
  'art', 'dev', 'doc', 'product'
);

$total_t1 = time();

foreach($svn_list as $svn) {
  $svn_dir = $svn_base.$svn;
  $backup_dir = $backup_base.$svn;
  $backup_file = "full-".date("Y_m_d-H_i_s");

  echo "backup '$svn_dir'\n";

  $t1 = time();

  $youngest = exec("svnlook youngest $svn_dir");

  exec("svnadmin dump --revision 0:$youngest $svn_dir > $backup_dir\\$backup_file");

  file_put_contents("$backup_dir\\last.txt", $youngest);

  $t2 = time();

  echo (($t2 - $t1) / 60)." m\r\n";
}

$total_t2 = time();

echo (($total_t2 - $total_t1) / 3600)." h\r\n";
?>

svnbackup-part.php

<?php
$svn_base = "H:\\SVN-Repos\\";
$backup_base = "G:\\SVN-Backups\\";

$svn_list = array(
  'art', 'dev', 'doc', 'product'
);

$total_t1 = time();

foreach($svn_list as $svn) {
  $svn_dir = $svn_base.$svn;
  $backup_dir = $backup_base.$svn;
  $backup_file = "part-".date("Y_m_d-H_i_s");

  echo "backup '$svn_dir' ";

  $t1 = time();

  $prev_youngest = file_get_contents("$backup_dir\\last.txt");

  $youngest = exec("svnlook youngest $svn_dir");

  if ($prev_youngest == $youngest) {
    echo "ignore\n\n";
    continue;
  }

  $begin_rev = $prev_youngest + 1;

  echo "from $begin_rev to $youngest\n\n";

  exec("svnadmin dump --incremental --revision $begin_rev:$youngest $svn_dir > $backup_dir\\$backup_file");

  file_put_contents("$backup_dir\\last.txt", $youngest);

  $t2 = time();

  echo (($t2 - $t1) / 60)." m\n\n";
}

$total_t2 = time();

echo (($total_t2 - $total_t1) / 3600)." h\n";
?>