Subversion的备份

想给Subversion服务器做简单的自动备份,也不知道别人是怎么弄的,自己想了个笨办法。

【环境】

A机:Subversion服务器,IP为192.168.1.16  B机:备份机器,IP为192.168.1.66

【策略】

每周六晚上23:30点进行hotcopy全量备份,每天晚上23:30点进行dump的增量备份。增量备份只是备份了从上次备份版本库到现在的变化。恢复的时候可以从dump恢复(时间较长),也可以先恢复hotcopy再从dump的增量恢复。

【思路】

将B的home目录mount在A上,这样A往自己的/mnt目录里备份,实际就备份在了B的/home里。当然之前需要测试是否连接。

【原理】

Subversion支持hotcopy和dump两种备份模式。hotcopy可以把整个代码库的目录结构拷贝出来,包括配置文件和数据文件等;而dump以可读的方式将repository中的内容导出,支持增量备份。恢复hotcopy比较简单,直接将文件夹拷贝回原来的位置即可,恢复dump文件必须通过命令行的方式导入,如果某个增量备份丢失会导致恢复dump失败。

svnadmin hotcopy是将整个库都“热”拷贝一份出来,包括库的钩子脚本、配置文件等;任何时候运行这个脚本都得到一个版本库的安全拷贝,不管是否有其他进程正在使用版本库。

svnadmin dump输出指定的修订版本。使用--revision选项可以指定一个单独的修订版本,或者一个修订版本的范围。如果忽略这个选项,所有版本库中的修订版本都会被转储。
Subversion在转储修订版本时,仅会输出与前一个修订版本之间的差异,通过这些差异足以从前一个修订版本中重建当前的修订版本。换句话说,在转储文件中的每一个修订版本仅包含这个修订版本作出的修改。这个规则的唯一一个例外是当前svnadmin dump转储的第一个修订版本。默认情况下,Subversion第一个转储的修订版本默认情况下会完整的保存目录、文件以及属性等数据。不过,这些都是可以改变的。如果转储时设置了--incremental选项,svnadmin会比较第一个转储的修订版本和版本库中前一个修订版本,就像对待其它转储的修订版本一样。转储时也是一样,转储文件中将仅包含第一个转储的修订版本的增量信息。这样的好处是,可以创建几个连续的小体积的转储文件代替一个大文件,比如:
$ svnadmin dump myrepos --revision 0:1000 > dumpfile1
$ svnadmin dump myrepos --revision 1001:2000 --incremental > dumpfile2
$ svnadmin dump myrepos --revision 2001:3000 --incremental > dumpfile3
这些转储文件可以使用下列命令装载到一个新的版本库中,比如:
$ svnadmin load newrepos < dumpfile1
$ svnadmin load newrepos < dumpfile2
$ svnadmin load newrepos < dumpfile3

svnlook 是Subversion提供的用来查看版本库中不同的修订版本和事务。svnlook youngest命令不需要选项,只会显示出HEAD的修订版本号。

【通用函数脚本】

  1 #!/bin/bash
  2 #Filename: tools.sh
  3 #***********************************************************
  4 #This scripts for set up svn backup environment
  5 #Author: qyddbear     
  6 #Email:                               
  7 #DATE:2012/05/23
  8 #Last modified by qyddbear on 2012/8/3 
  9 #***********************************************************
 10 
 11 setup_env()
 12 {
 13     DUMP="/usr/bin/svnadmin dump"
 14     LOOK="/usr/bin/svnlook youngest"
 15     HOTCOPY="/usr/bin/svnadmin hotcopy"
 16     SVN_ROOT=/home/svn
 17     SVN_BACKUP=/mnt/svn_backup
 18     BACKUP_DATE=$(date +%Y-%m-%d)
 19     ERROR_LOG=$SVN_BACKUP/backup_error.log
 20     THIS_FILE_NUM=$SVN_BACKUP/this_repo_version.log
 21     LAST_FILE_NUM=$SVN_BACKUP/last_repo_version.log
 22     ALL_BACKUP_NUM=$SVN_BACKUP/all_backup_version.log
 23 
 24     if [ $1 == "full" ];then
 25         SVN_BACKUP_DIR=$SVN_BACKUP/"full_"$BACKUP_DATE
 26         LOGFILE=$SVN_BACKUP/full_backup.log
 27     else
 28         SVN_BACKUP_DIR=$SVN_BACKUP/"increment_"$BACKUP_DATE
 29         LOGFILE=$SVN_BACKUP/increment_backup.log
 30     fi
 31 
 32     REPO_NAME_LIST=$(ls $SVN_ROOT)
 33     echo $LOGFILE
 34     echo $SVN_BACKUP_DIR
 35 }
 36 
 37 check_mount_point()
 38 {
 39     echo $1
 40     ping -c 1 -w 1 $1 &>/dev/null
 41     if [ $? = 0 ]
 42     then
 43         df -k | grep $1 &>/dev/null || mount $1:/home /mnt
 44         return 0
 45     else
 46         echo "$BACKUP_DATE==>Backup Computer[$1] already shutdown!" >>$ERROR_LOG 
 47          echo " " >>$ERROR_LOG
 48         return 1 
 49     fi
 50 }
 51 
 52 
 53 #=====================================================================
 54 #check backup directory, if not exist, mkdir
 55 #=====================================================================
 56 check_backup_dir()
 57 {
 58     if [ ! -d $SVN_BACKUP ];then
 59          mkdir $SVN_BACKUP
 60          chmod g+s $SVN_BACKUP
 61     fi
 62 
 63     if [ -d $SVN_BACKUP_DIR ];then
 64          echo "Thers is no need backup again!" >>$LOGFILE
 65     else
 66          mkdir $SVN_BACKUP_DIR 
 67          chmod g+s $SVN_BACKUP_DIR 
 68     fi
 69 }
 70 
 71 
 72 send_emails()
 73 {
 74     if [ $1 == "succeed" ];then
 75          MAILBODY=
 76     else
 77         MAILBODY=
 78     fi
 79     echo $MAILBODY | mail -s $1 qyddbear@123.com
 80 }
 81 
 82 
 83 start_full_backup()
 84 {
 85     echo " ">>$LOGFILE
 86     echo "********************$(date +%Y-%m-%d_%T)********************" >>$LOGFILE
 87     for repo_name in $REPO_NAME_LIST
 88     do
 89         #get repo version
 90          get_repo_version=$($LOOK $SVN_ROOT/$repo_name)
 91         
 92          #hotcopy full backup, key step
 93          $HOTCOPY $SVN_ROOT/$repo_name $SVN_BACKUP_DIR/$repo_name
 94                echo "$(date +%T)==> repository:[$repo_name] at version($get_repo_version) Hotcopy Successfull Full Backup !" >>$LOGFILE
 95          echo " ">>$LOGFILE
 96 
 97         #dump full backup, key step
 98         $DUMP $SVN_ROOT/$repo_name > $SVN_BACKUP_DIR/"$repo_name"_"0"-"$get_repo_version".dump
 99                echo "$(date +%T)==> repository:[$repo_name] at version($get_repo_version) Dump Successfull Full Backup !" >>$LOGFILE
100          echo " ">>$LOGFILE
101 
102          #output full repo version number to a txt for incremental backup usage
103          echo "$get_repo_version" > $LAST_FILE_NUM 
104         echo "$get_repo_version" >> $ALL_BACKUP_NUM
105     done
106 }
107 
108 
109 start_increment_backup()
110 {    
111     echo " ">>$LOGFILE
112     echo "*******************$(date +%Y-%m-%d_%T)******************" >>$LOGFILE
113       for repo_name in $REPO_NAME_LIST
114       do
115         lastnum=$(cat $LAST_FILE_NUM)
116         echo "$(date +%T)==> repository:[$repo_name] last time version_number : $lastnum" >>$LOGFILE
117         let beginnum=($lastnum+1)
118         echo "$(date +%T)==> repository:[$repo_name] increment backup will begin from : $beginnum" >> $LOGFILE
119         thisnum=$($LOOK $SVN_ROOT/$repo_name)
120         echo "$(date +%T)==> repository:[$repo_name] this time version_number : $thisnum" >>$LOGFILE
121         
122             if [ $thisnum -ne $lastnum ];then
123             $DUMP $SVN_ROOT/$repo_name -r $beginnum:$thisnum --incremental > $SVN_BACKUP/increment_"$BACKUP_DATE"/"$repo_name"_"$beginnum"-"$thisnum".dump
124             echo "$(date +%T)==> repository:[$repo_name] version(from $beginnum to $thisnum) backup successful!" >>$LOGFILE
125         else
126                   echo "$(date +%T)==> repository:[$repo_name] has no new version!!" >>$LOGFILE
127             
128         fi
129     echo " ">>$LOGFILE
130     echo "$thisnum" > $LAST_FILE_NUM
131     echo "$thisnum" >> $ALL_BACKUP_NUM
132     done
133     
134 }

【全量备份脚本】

 1 #!/bin/bash
 2 #Filename: svn_full_backup.sh
 3 #*******************************************************
 4 #This scripts for svn full bakcup
 5 #Author: qyddbear     
 6 #Email:                            
 7 #DATE:2012/05/23 
 8 #Last modified by qyddbear on 2012/8/3 
 9 #*******************************************************
10 
11 . ./tools.sh
12 
13 setup_env full
14 
15 #backup server ip
16 check_mount_point 192.168.1.66
17 
18 check_backup_dir
19 
20 start_full_backup

【增量备份脚本】

 1 #!/bin/bash
 2 #Filename: svn_increment_backup.sh
 3 #*******************************************************
 4 #This scripts for svn increment bakcup
 5 #Author: qyddbear    
 6 #Email:                            
 7 #DATE:2012/05/24 
 8 #Last modified by qyddbear on 2012/8/3
 9 #*******************************************************
10 
11 . ./tools.sh
12 
13 setup_env increment
14 
15 #backup server ip
16 check_mount_point 192.168.1.66
17 
18 check_backup_dir
19 
20 start_increment_backup

【设置备份时间】

配置 /etc/crontab 文件,用crontab来定在每周6的23:30分执行任务:

30 23 * * 6 /home/scripts/svn_full_backup.sh
重新启动/etc/init.d/crond restart
 
注:前五个以4个空格分隔开的值依次表示:分、时、日、月、周,如果取所有值就是打*号,如果想周期性的运行一个任务,crontab也接受范围指定,比如说一天中的早8点到晚6点每隔一小时(就是每两小时,将会在8,10,12,14,16,18执行)执行,这个删除命令这样写:

* 8-18/2 * * * root rm -rf /root/febhost/dat/* /root/febhost/log/*
第一个字段是分钟,取值范围:0-59
第二个字段是小时。取值范围:0-23
第三个字段是一个月中的第几天,取值范围:1-31
第四个字段是一年中的第几个月,取值范围:1-12
最后一个字段是一个星期中的第几天,以星期天开始依次的取值为0~7,0、7都表示星期天。
下一个字段是执行该命令的用户身份,这里是root用户,最后一个字段就是定时运行的命令。

 
【如何知道备份是否完整呢?】
 
备份完整性检查的思路是:对备份的库运行 svnlook youngest,如果能正确打印出最新的版本号,则表明备份文件没有缺失;如果备份中断,则运行svnlook youngest会出错,说明备份不完整。

【备份恢复】

首先要建立一个新的版本库:
svnadmin create --fs-type=fsfs /home/svn/project
然后再执行load,还原数据。恢复顺序从低版本逐个恢复到高版本;即,先恢复最近的一次完整备份 weekly_full_backup.071201(举例),然后恢复紧挨着这个文件的增量备份 daily_incremental_backup.071202,再恢复后一天的备份071203,依次类推。如下: 
svnadmin load /home/svn/project < /home/backup/svn/weekly_full_backup.071201 
svnadmin load /home/svn/project < /home/backup/svn/daily_incremental_backup.071202 
svnadmin load /home/svn/project < /home/backup/svn/daily_incremental_backup.071203 
 
原文地址:https://www.cnblogs.com/qyddbear/p/2862112.html