SVN仓库备份 作者: ciniao 时间: 2015-02-02 分类: 技术 * 本文发布时间较久,请自行判断有效性 #### svn备份的三种方法 1. svnadmin dump 1. svnadmin hotcopy 1. svnsync 注意:svn备份不宜采用普通的文件拷贝方式(除非你备份的时候将库暂停),如copy命令、rsync命令。 #### 优缺点 第一种svnadmin dump是官方推荐的备份方式,优点是比较灵活,可以全量备份也可以增量备份,并提供了版本恢复机制。 缺点是:如果版本比较大,如版本数增长到数万、数十万,那么dump的过程将非常慢;备份耗时,恢复更耗时;不利于快速进行灾难恢复。 个人建议在版本数比较小的情况下使用这种备份方式。 第二种svnadmin hotcopy原设计目的估计不是用来备份的,只能进行全量拷贝,不能进行增量备份; 优点是:备份过程较快,灾难恢复也很快;如果备份机上已经搭建了svn服务,甚至不需要恢复,只需要进行简单配置即可切换到备份库上工作。 缺点是:比较耗费硬盘,需要有较大的硬盘支持 第三种svnsync实际上是制作2个镜像库,当一个坏了的时候,可以迅速切换到另一个。不过,必须svn1.4版本以上才支持这个功能。 优点是:当制作成2个镜像库的时候起到双机实时备份的作用; 缺点是:当作为2个镜像库使用时,没办法做到“想完全抛弃今天的修改恢复到昨晚的样子”;而当作为普通备份机制每日备份时,操作又较前2种方法麻烦。 #### dump 命令语法: ``` svnadmin dump 版本库路径及名称 –revision 导出的版本号 > 导出的命名 ``` 增量备份:使用svnadmin dump的 `--incremental`选项来实现 ``` svnadmin dump 版本库路径及名称 –revision 上次导出的版本号:到本次要导出到的版本号 –incremental > 导出的命名 ``` 进行数据还原 ``` svnadmin load 版本库路径及名称 < ./bak.dump ```  完整python脚本 ``` import subprocess import os import re def backupSvnRepositories(svn_repository_path, backup_dir): """ 备份SVN仓库里所有项目,首次全量备份,后续增量备份并记录版本号 :param svn_repository_path: SVN仓库在本地的Linux系统下的路径 :param backup_dir: 备份存放的Linux系统下的目录 """ # 判断备份目录是否存在,不存在则创建,使用Linux的mkdir -p命令确保目录创建的递归性 if not os.path.exists(backup_dir): os.makedirs(backup_dir) # 获取SVN仓库路径下所有项目文件夹 projects = [f for f in os.listdir(svn_repository_path) if os.path.isdir(os.path.join(svn_repository_path, f))] for project in projects: project_path = os.path.join(svn_repository_path, project) backup_project_path = os.path.join(backup_dir, project) if not os.path.exists(backup_project_path): os.makedirs(backup_project_path) # 获取最新的版本号 youngest_command = ["svnlook","youngest",project_path] result = subprocess.run(youngest_command, capture_output=True, text=True) youngest = result.stdout.strip() if youngest=='': continue # 记录版本号的文件路径 version_file_path = os.path.join(backup_project_path, "_last_backup_version.txt") # 判断是否存在上次备份记录的版本号,以此决定全量还是增量备份 if os.path.exists(version_file_path): with open(version_file_path, 'r') as f: last_version = f.read().strip() if last_version == youngest: print(project,"已是最新,无需备份") continue backup_command = ['bash', '-c',f"svnadmin dump --incremental --revision {last_version}:{youngest} {project_path} > {backup_project_path}/{youngest}.dump"] proc = subprocess.Popen(backup_command,stdout=subprocess.PIPE, stderr=subprocess.PIPE) _, output = proc.communicate() #output.decode('utf-8') if os.path.exists(f"{backup_project_path}/{youngest}.dump"): #dump成功 subprocess.run(["gzip", f"{backup_project_path}/{youngest}.dump"], shell=False) with open(version_file_path, 'w') as f: f.write(youngest) print(project,"增量备份成功",youngest) else: #进行完整备份 backup_command = ['bash', '-c',f"svnadmin dump --revision 0:{youngest} {project_path} > {backup_project_path}/full.dump"] proc = subprocess.Popen(backup_command,stdout=subprocess.PIPE, stderr=subprocess.PIPE) _, output = proc.communicate() #output.decode('utf-8') if os.path.exists(f"{backup_project_path}/full.dump"): #dump成功 subprocess.run(["gzip", f"{backup_project_path}/full.dump"], shell=False) with open(version_file_path, 'w') as f: f.write(youngest) print(project,"全量备份成功",youngest) if __name__ == "__main__": svnRepositoryLocalPath = "/home/svnadmin/rep" # 替换为你实际的本地SVN仓库路径 backupDirectory = "/home/svnadmin/dump/data" # 替换为你想存放备份的实际目录 backupSvnRepositories(svnRepositoryLocalPath, backupDirectory) ``` #### hotcopy 语法: ``` svnadmin hotcopy 路径/repository 路径/backup ```  增量备份 如果此时你需要删除冗余的日志文件只需在后面添加`--clean-logs`参数即可,如果需要增量备份后面加入`--incremental`即可  如果要做还原的话可以直接将备份文件里面的东西直接拷贝到版本库相对路径下即可。相比dump来说,hotcopy更加方便省事 **Svn hotcopy备份脚本** Windows: ``` @echo 正在备份版本库%1...... @%SVN\_HOME%\\bin\\svnadmin hotcopy %1 %BACKUP\_DIRECTORY%\\%2 @echo 版本库%1成功备份到了%2! ``` Backup脚本 ``` echo off rem Subversion的安装目录 set SVN_HOME="D:\Program Files\VisualSVN Server" rem 所有版本库的父目录 set SVN_ROOT=D:\Repositories rem 备份的目录 set BACKUP_SVN_ROOT=E:\Backup set BACKUP_DIRECTORY=%BACKUP_SVN_ROOT%\%date:~0,10% if exist %BACKUP_DIRECTORY% goto checkBack echo 建立备份目录%BACKUP_DIRECTORY%>>%SVN_ROOT%/backup.log md %BACKUP_DIRECTORY% rem 验证目录是否为版本库,如果是则取出名称备份 for /r %SVN_ROOT% %%I in (.) do @if exist "%%I\conf\svnserve.conf" %SVN_ROOT%\simpleBackup.bat "%%~fI" %%~nI goto end :checkBack echo 备份目录%BACKUP_DIRECTORY%已经存在,请清空。 goto end :end ``` 这里只有日期定义格式为“-”才能正常运行,如果是“/”就会提示找不到备份目录须要定义日期格式 Windows下定义格式 ``` echo "%date:~0,10%" echo "%date:~0,4%\_%date:~5,2%\_%date:~8,2%" ``` ####svnsync svnsync是Subversion提供的一个用于同步版本库的工具,通过svnsync同时可以达到备份SVN版本库的目的。 svnsync的使用方法如下: 首先进行初始化,建立目标库和源库之间的同步关系 ``` svnsync init 目标库URL 源库URL ``` 用svnsync sync开始真正的同步 ``` svnsync sync 目标库URL ``` 试验 ``` 1、131启动svn svnserve -d -r /application/svndata/ 2、132安装svn并创建库 yum install -y subversion mkdir /application/ svnserve -d -r /application/ svnadmin create /application/svnback 3、修改目标库的脚本pre-revprop-change cd /application/svnback/hooks/ cp pre-revprop-change.tmpl pre-revprop-change vi pre-revprop-change # 编辑pre-revprop-change钩子,将最后一行的 `exit 1` 改为 `exit 0` chmod a+x pre-revprop-change 4、初始化 svnsync init file:///application/svnback/ svn://192.168.10.131/sadoc [root@k8s02 hooks]# svnsync init file:///application/svnback/ svn://192.168.10.131/sadoc Authentication realm: 46cc3a34-e1e1-45b5-bdf4-a20ef78c2ca7 Password for 'root': Authentication realm: 46cc3a34-e1e1-45b5-bdf4-a20ef78c2ca7 Username: zhangsan Password for 'zhangsan': 让输入root的密码,131的svn账号和密码 5、同步 svnsync sync --non-interactive file:///application/svnback/ [root@k8s02 db]# svn list file:///application/svnback/ a.txt b.txt c.txt d.txt e.txt test.log 你好清晨.txt 6、设置自动同步钩子 k8s02需要设置一个同步的账号密码 cd /application/svnback/conf [root@k8s02 conf]# cat svnserve.conf |grep -v '#'|grep -v ^$ [general] anon-access = none auth-access = write password-db = passwd authz-db = authz [root@k8s02 conf]# cat passwd [users] zhaoliu = 123456 [root@k8s02 conf]# cat authz [svnback:/] zhaoliu = rw k8s01需要设置钩子 cd /application/svndata/sadoc/hooks cp post-commit.tmpl post-commit chmod a+x post-commit vi post-commit 将mailer.py commit "$REPOS" "$REV" /path/to/mailer.conf删掉 添加内容 svnsync sync --non-interactive svn://192.168.10.132/svnback --sync-username zhaoliu --sync-password 123456 ##--non-interactive #非交互式 观察变化 [root@k8s02 hooks]# svn list file:///application/svnback/ ``` 标签: 运维