SVN迁移及备份的⽅法【转】
备份策略
==============
svn备份⼀般采⽤三种⽅式:
1)svnadmin dump
2)svnadmin hotcopy
3)svnsync.
注意,svn备份不宜采⽤普通的⽂件拷贝⽅式(除⾮你备份的时候将库暂停),如copy命令、rsync命令。
笔者曾经⽤ rsync命令来做增量和全量备份,在季度备份检查审计中,发现备份出来的库⼤部分都不可⽤,因此最好是⽤svn本⾝提供的功能来进⾏备份。
优缺点分析
==============
第⼀种svnadmin dump是官⽅推荐的备份⽅式,优点是⽐较灵活,可以全量备份也可以增量备份,并提供了版本恢复机制。
缺点是:如果版本⽐较⼤,如版本数增长到数万、数⼗万,那么dump的过程将⾮常慢;备份耗时,恢复更耗时;不利于快速进⾏灾难恢复。
个⼈建议在版本数⽐较⼩的情况下使⽤这种备份⽅式。
第⼆种svnadmin hotcopy原设计⽬的估计不是⽤来备份的,只能进⾏全量拷贝,不能进⾏增量备份;
优点是:备份过程较快,灾难恢复也很快;如果备份机上已经搭建了svn服务,甚⾄不需要恢复,只需要进⾏简单配置即可切换到备份库上⼯作。
缺点是:⽐较耗费硬盘,需要有较⼤的硬盘⽀持(俺的备份机有1TB空间,呵呵)。
第三种svnsync实际上是制作2个镜像库,当⼀个坏了的时候,可以迅速切换到另⼀个。不过,必须svn1.4版本以上才⽀持这个功能。
优点是:当制作成2个镜像库的时候起到双机实时备份的作⽤;
缺点是:当作为2个镜像库使⽤时,没办法做到“想完全抛弃今天的修改恢复到昨晚的样⼦”;⽽当作为普通备份机制每⽇备份时,操作⼜较前2种⽅法⿇烦。
备份的命令
==============
全备份:使⽤svnadmin dump或svnadmin hotcopy或svnsync来做,
hotcopy:
svnadmin hotcopy path/to/repository path/to/backup –clean-logs
dump:
svnadmin dump 版本库路径及名称 –revision 导出的版本号> 导出的命名
增量备份:使⽤svnadmin dump的–incremental选项来实现
svnadmin dump 版本库路径及名称 –revision 上次导出的版本号:到本次要导出到的版本号 –incremental > 导出的命名
⼀个技巧:如果你有⼀个较⼤的Subsersion版本库⽽你⼜想⽤最少的空间来将它备份下来,⽤这个命令(请将/repo替换成你的版本库路径)吧:svnadmin dump –deltas /repo |bzip2 |tee dump.bz2 | md5sum >dump.md5
分步解释:最重要的⼀步是 -deltas,将消耗更多的CPU资源,但拥有更有效的差异存储办法。
bzip2压缩⽅案⽐gzip慢,但换来的更好的压缩率。
更有趣的是,tee⽅法将压缩的数据流转向到⽂件dump.bz2,同时将其输出到标准输出,后者有转向给了MD5摘要计算⼯具。
还原命令
==============
还原版本:svnadmin load 要恢复的版本库路径及名称 < 导出的命名
svnadmin hotcopy path/to/repository path/to/backup –clean-logs
svnadmin dump
perl怎么下载
==============
这是subversion官⽅推荐的备份⽅式。
1)定义备份策略:
备份频度:每周六进⾏⼀次全量备份,每周⽇到周五进⾏增量备份
备份地点:备份存储路径到/home/backup/svn/
备份命名:全量备份⽂件名为:weekly_dd,增量备份⽂件命名为:dd
备份时间:每晚21点开始
备份检查:每⽉末进⾏svnadmin load恢复试验。
2)建⽴全量备份脚本:
在~/下建⽴⼀个perl脚本⽂件,名为weekly_backup.pl,执⾏全量备份,并压缩备份⽂件,代码如下(本代码只针对⼀个库的备份,如果是多个库请做相应改动):
#!/usr/bin/perl -w
my $svn_repos="/home/svn/repos/project1";
my $backup_dir="/home/backup/svn/";
my $next_backup_file = "weekly_fully_backup.".`date +%Y%m%d`;
$youngest=`svnlook youngest $svn_repos`;
chomp $youngest;
print "Backing up to revision $youngest\n";
my $svnadmin_cmd="svnadmin dump --revision 0:$youngest $svn_repos >$backup_dir/$next_backup_file";
`$svnadmin_cmd`;
open(LOG,">$backup_dir/last_backed_up"); #记录备份的版本号
print LOG $youngest;
close LOG;
#如果想节约空间,则再执⾏下⾯的压缩脚本
print "Compressing \n";
print `gzip -g $backup_dir/$next_backup_file`;
3)建⽴增量备份脚本:
在全量备份的基础上,进⾏增量备份:在~/下建⽴⼀个perl脚本⽂件,名为:daily_backup.pl,代码如下:
#!/usr/bin/perl -w
my $svn_repos="/home/svn/repos/project1";
my $backup_dir="/home/backup/svn/";
my $next_backup_file = "daily_incremental_backup.".`date +%Y%m%d`;
open(IN,"$backup_dir/last_backed_up");
$previous_youngest = <IN>;
chomp $previous_youngest;
close IN;
$youngest=`svnlook youngest $svn_repos`;
chomp $youngest;
if ($youngest eq $previous_youngest)
{
print "No new revisions to backup.\n";
exit 0;
}
my $first_rev = $previous_youngest + 1;
print "Backing up revisions $youngest ...\n";
my $svnadmin_cmd = "svnadmin dump --incremental --revision $first_rev:$youngest $svn_repos > $backup_dir/$next_backup_file";
`$svnadmin_cmd`;
open(LOG,">$backup_dir/last_backed_up"); #记录备份的版本号
print LOG $youngest;
close LOG;
#如果想节约空间,则再执⾏下⾯的压缩脚本
print "Compressing \n";
print `gzip -g $backup_dir/$next_backup_file`;
4)配置/etc/crontab⽂件
配置 /etc/crontab ⽂件,指定每周六执⾏weekly_backup.pl,指定周⼀到周五执⾏daily_backup.pl;
具体步骤俺就不啰嗦了.
5)备份恢复检查
在⽉底恢复检查中或者在灾难来临时,请按照如下步骤进⾏恢复:恢复顺序从低版本逐个恢复到⾼版本;即,先恢复最近的⼀次完整备份
weekly_full_backup.071201(举例),然后恢复紧挨着这个⽂件的增量备份 daily_incremental_backup.071202,再恢复后⼀天的备份071203,依次类推。如下:
user1>mkdir newrepos
user1>svnadmin create newrepos
user1>svnadmin load newrepos < weekly_full_backup.071201
user1>svnadmin load newrepos < daily_incremental_backup.071202
user1>svnadmin load newrepos < daily_incremental_backup.071203
....
如果备份时采⽤了gzip进⾏压缩,恢复时可将解压缩和恢复命令合并,简单写成:
user1>zcat weekly_full_backup.071201 | svnadmin load newrepos
user1>zcat daily_incremental_backup.071202 | svnadmin load newrepos
...
svnadmin hotcopy整库拷贝⽅式
==============
svnadmin hotcopy是将整个库都“热”拷贝⼀份出来,包括库的钩⼦脚本、配置⽂件等;任何时候运⾏这个脚本都得到⼀个版本库的安全拷贝,不管是否有其他进程正在使⽤版本库。
因此这是俺青睐的备份⽅式。
1)定义备份策略
备份频度:每天进⾏⼀次全量备份,
备份地点:备份⽬录以⽇期命名,备份路径到 /home/backup/svn/${mmdd}
备份保留时期:保留10天到15天,超过15天的进⾏删除。
备份时间:每晚21点开始
备份检查:备份完毕后⾃动运⾏检查脚本、⾃动发送报告。
2)建⽴备份脚本
在⾃⼰home⽬录 ~/下创建⼀个⽂件,backup.sh:
#!/bin/bash
SRCPATH=/home/svn/repos/; #定义仓库parent路径
DISTPATH=/home/backup/svn/`date +\%m%d`/ ; #定义存放路径;
if [ -d "$DISTPATH" ]
then
else
mkdir $DISTPATH
chmod g+s $DISTPATH
fi
echo $DISTPATH
svnadmin hotcopy $SRCPATH/Project1 $DISTPATH/Project1 >/home/backup/svn/cpreport.log 2>&1;
svnadmin hotcopy $SRCPATH/Project2 $DISTPATH/Project2
cp $SRCPATH/access $DISTPATH; #备份access⽂件
cp $SRCPATH/passwd $DISTPATH; #备份passwd⽂件
perl /home/backup/svn/backup_check.pl #运⾏检查脚本
perl /home/backup/svn/deletDir.pl #运⾏删除脚本,对过期备份进⾏删除。
3)建⽴检查脚本
在上⾯指定的地⽅/home/backup/svn/下建⽴⼀个perl脚本:backup_check.pl
备份完整性检查的思路是:对备份的库运⾏ svnlook youngest,如果能正确打印出最新的版本号,则表明备份⽂件没有缺失;如果运⾏报错,则说明备份不完整。我试过如果备份中断,则运⾏svnlook youngest会出错。
4)定义删除脚本
由于是全量备份,所以备份不宜保留太多,只需要保留最近10来天的即可,对于超过15天历史的备份基本可以删除了。
在/home/backup/svn/下建⽴⼀个perl脚本:deletDir.pl
5)修改/etc/crontab ⽂件
在该⽂件中指定每晚21点执⾏“backup.sh”脚本。
svnsync备份
==============
使⽤svnsync备份很简单,步骤如下:
1)在备份机上创建⼀个空库:svnadmin create Project1
2)更改该库的钩⼦脚本pre-revprop-change(因为svnsync要改这个库的属性,也就是要将源库的属性备份到这个库,所以要启⽤这个脚本):
cd SMP/hooks;
pl pre-revprop-change;
chmod 755 pre-revprop-change;
vi pre-revprop-change;
将该脚本后⾯的三句注释掉,或者⼲脆将它弄成⼀个空⽂件。
3)初始化,此时还没有备份任何数据:
svnsync init file:///home/backup/svn/svnsync/Project1/ svntest.subversion/repos/Project1
语法是:svnsync init {你刚创建的库url} {源库url}
注意本地url是三个斜杠的:///
4)开始备份(同步):
svnsync sync file:///home/backup/svn/svnsync/Project1
5)建⽴同步脚本
备份完毕后,建⽴钩⼦脚本进⾏同步。在源库/hooks/下建⽴/修改post-commit脚本,在其中增加⼀⾏,内容如下:
/usr/bin/svnsync sync --non-interactive file:///home/backup/svn/svnsync/Project1
你可能已经注意到上⾯的备份似乎都是本地备份,不是异地备份。实际上,我是通过将远程的备份机mount(请参阅mount命令)到svn服务器上来实现的,逻辑上看起来是本地备份,物理上实际是异地备份。
完!
以下是subversion官⽅推荐的备份⽅式。
关闭所有运⾏的进程,并确认没有程序在访问存储库(如 httpd、svnserve 或本地⽤户在直接访问)。
备份svn存储库
#压缩备份
svnadmin dump /home/workhome/svn/repository | gzip > ~/
#不压缩备份
svnadmin dump /home/workhome/svn/repository > ~/repository-backup.svn
恢复svn存储库
#建⽴新的svn存储库
svnadmin create /home/workhome/svn/newrepository
#确认成功与否
ls -l /home/workhome/svn/newrepository
#导⼊存储库数据
svnadmin load /home/workhome/svn/newrepository < ~/repository-backup.svn
SVN数据库迁移⽅法⼀
称之为SVN全库操作,或称SVN全局备份并恢复,版本库数据的移植:svnadmin dump、svnadmin load
导出:
$svnadmin dump repos > dumpfile //将指定的版本库导出成⽂件dumpfile
新建:
$svnadmin create newrepos
导⼊:
$svnadmin load newrepos < dumpfile
SVN数据库迁移⽅法⼆
增量备份或批次备份,批次恢复,特定reversion导出:
$svnadmin dump repos –r 23 >rev-23.dumpfile //将version23导出
$svnadmin dump repos –r 100:200 >rev-100-200.dumpfile //将version100~200导出
批次导出:对⽐较⼤的库可以批次导出,便于备份
$svnadmin dump repos –r 0:1000 >0-1000.dumpfile
$svnadmin dump repos –r 1001:2000 --incremental >1001-2000.dumpfile
$svnadmin dump repos –r 2001:3000 --incremental >2001:3000.dumpfile
批次导⼊,将这⼏个备份⽂件装载到⼀个新的版本库中
$svnadmin load newrepos < 0-1000.dumpfile
$svnadmin load newrepos < 1001-2000.dumpfile
$svnadmin load newrepos < 2001:3000.dumpfile
SVN数据库迁移⽅法三
导出后,在导⼊时对库做分库整理或其它整理操作过滤版本库历史:
假设有⼀个包含三个项⽬的版本库: calc,calendar,和 spreadsheet。它们在版本库中的布局如下:
/
trunk/
branches/
tags/
calendar/
trunk/
branches/
tags/
spreadsheet/
trunk/
branches/
tags/
现在要把这三个项⽬转移到三个独⽴的版本库中。⾸先,转储整个版本库:
$ svnadmin dump /path/to/repos > repos-dumpfile
* Dumped revision 0.
* Dumped revision 1.
* Dumped revision 2.
* Dumped revision 3.
然后,将转储⽂件三次送⼊过滤器,每次仅保留⼀个顶级⽬录,就可以得到三个转储⽂件:
$ cat repos-dumpfile | svndumpfilter include calc > calc-dumpfile
$ cat repos-dumpfile | svndumpfilter include calendar > cal-dumpfile
$ cat repos-dumpfile | svndumpfilter include spreadsheet > ss-dumpfile
现在你必须要作出⼀个决定了。这三个转储⽂件中,每个都可以⽤来创建⼀个可⽤的版本库,不过它们保留了原版本库的精确路径结构。也就是说,虽然项⽬calc 现在独占了⼀个版本库,但版本库中还保留着名为calc的顶级⽬录。如果希望trunk、tags和branches这三个⽬录直接位于版本库的根路径下,你可能需要编辑转储⽂件,调整Node-path和Copyfrom-path头参数,将路径calc/删除。同时,你还要删除转储数据中创建 calc⽬录的部分。⼀般来说,就是如下的⼀些内容:
Node-path: calc
Node-action: add
Node-kind: dir
Content-length: 0
警告:
如果你打算通过⼿⼯编辑转储⽂件来移除⼀个顶级⽬录,注意不要让你的编辑器将换⾏符转换为本地格式(⽐如将\r\n转换为\n)。否则⽂件的内容就与所需的格式不相符,这个转储⽂件也就失效了。
剩下的⼯作就是创建三个新的版本库,然后将三个转储⽂件分别导⼊:
$ svnadmin create calc; svnadmin load calc < calc-dumpfile
$ svnadmin create calendar; svnadmin load calendar < cal-dumpfile
$ svnadmin create spreadsheet; svnadmin load spreadsheet < ss-dumpfile
svndumpfilter 的两个⼦命令都可以通过选项设定如何处理“空”修订版本。如果某个指定的修订版本仅包含路径的更改,过滤器就会将它删除,因为当前为空的修订版本通常是⽆⽤的甚⾄是让⼈讨厌的。为了让⽤户有选择的处理这些修订版本,svndumpfilter提供了以下命令⾏选项:
--drop-empty-revs
不⽣成任何空修订版本,忽略它们。
--renumber-revs
如果空修订版本被剔除(通过使⽤--drop-empty-revs选项),依次修改其它修订版本的编号,确保编号序列是连续的。
--preserve-revprops
如果空修订版本被保留,保持这些空修订版本的属性(⽇志信息,作者,⽇期,⾃定义属性,等等)。如果不设定这个选项,空修订版本将仅保留初始时间戳,以及⼀个⾃动⽣成的⽇志信息,表明此修订版本由svndumpfilter处理过。
尽管svndumpfilter⼗分有⽤,能节省⼤量的时间,但它却是把不折不扣的双刃剑。⾸先,这个⼯具对路径语义极为敏感。仔细检查转储⽂件中的路径是不是以斜线开头。也许Node-path和Copyfrom-path这两个头参数对你有些帮助。
Node-path: spreadsheet/Makefile
如果这些路径以斜线开头,那么你传递给svndumpfilter include和svndumpfilter exclude的路径也必须以斜线开头(反之亦然)。如果因为某些原因转储⽂件中的路径没有统⼀使⽤或不使⽤斜线开头,也许需要修正这些路径,统⼀使⽤斜线开头或不使⽤斜线开头。
此外,复制操作⽣成的路径也会带来⿇烦。Subversion⽀持在版本库中进⾏复制操作,也就是复制⼀个
存在的路径,⽣成⼀个新的路径。问题
是,svndumpfilter保留的某个⽂件或⽬录可能是由某个svndumpfilter排除的⽂件或⽬录复制⽽来的。也就是说,为了确保转储数据的完整性,svndumpfilter需要切断这些复制⾃被排除路径的⽂件与源⽂件的关系,还要将这些⽂件的内容以新建的⽅式添加到转储数据中。但是由于Subversion版本库转储⽂件格式中仅包含了修订版本的更改信息,因此源⽂件的内容基本上⽆法获得。如果你不能确定版本库中是否存在类似的情况,最好重新考虑⼀下到底保留/排除哪些路径。备份环境注意点:
1、确保没有其他进程访问版本库,关闭apache、svnserve服务
2、成为版本库的管理员,如果以其他⾝份还原版本库,可能会改变版本库⽂件的访问权限,导致在恢复后依旧⽆法访问
3、svnadmin recover /path/to/repos
4、重新启动服务进程
SVN数据库整理⽅法
不经过dump,load操作,实现SVN数据库整理操作,先设计好调整后的⽬录, 然后打开版本库, 选中要调
整或转移的⽂件(⽂件夹)-->右键拖住,不要松⼿-->然后将要转移的⽂件(⽂件夹)拖⾄⽬标⽂件夹-->松⼿--> 选择move items to here-->完成
每经过这样的调整,⼤家都会担⼼历史记录是否还会存在, TortoiseSVN在默认情况下, 是不会显⽰出来的,需要将⼀个选项去除.
如此可实现基于库的调整操作,但事事不是尽如⼈意的,这样的⼀次操作下来,revision会增长好多。
我的想法是:
停⽌当前 SVN服务,将当前的SVN库直接进⾏整理,就像整理存储在电脑中的⽂件夹⼀样,然后开启SVN服务,即时显⽰调整后的效果,哈哈..是不是有点异想天开,其实我也觉得这是不太可能的,除⾮使⽤⼯具访问,否则SVN库不是显⽰可见的,希望以后啥配置管理⼯具可以让管理员有这样的权限.
实验:
⼀、在迁出服务器执⾏:
> csvn stop
Stopping
Waiting for CSVN Console
Waiting for CSVN Console
Stopped CSVN Console.
> csvn-httpd stop
Stopping Subversion Edge Apache Server: done
> svnadmin dump /home/svn/csvn/data/repositories/camp | gzip >camp_
* Dumped revision 4495.
* Dumped revision 4496.
> ls
camp camp_ cpst csvn csvn-httpd docm 参考:
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论