先啰嗦下为什么要使用svndumpfilter…

svn库用久了以后就会越来越大,进行整体文件打包备份的时候,发现压力山大…尤其是美术团队也在使用svn进行重要美术资源管理的时候…….几百g的资源同步备份的盛况对于机器来说是难以承受的压力,尤其是当存在多种备份方式(比如本地多机器拷贝、远程机器上传备份)。几十kb的速度去承担几百g的备份是痛苦的事情。

公司的运维又不给力,围观了下他们部署在我们服务器的批处理备份代码,就一个简单的对svn的仓库目录直接用winrar压缩,然后用rsync同步,这是多么粗糙的方案,当然也不是说错误,只是说过于暴力了点,且可控性太差,当想要过滤某些文件的时候就无法实现了。

一开始我想的方案也是压缩打包,用python实现,这样过滤文件的时候,可以在逻辑上加处理,这样可以屏蔽下想要过滤的东西,代码如下:

#-*- coding=gbk -*-

import tarfile
import os
import time
import threading
import datetime
import shutil
import subprocess
from myEmail import Mailer ignoreNames = ["ArtGroup", ".svn"]
TargetDir = "D:\\02_ucgame_Svn_Repositories"
BackUp = "svn_backup_%s.tar.gz"
ShareDir = "z:\\backup"
mailTitle = "[UCCDTest] svn backup analyze %s"
receivers = [
"account@qq.com",
"account@qq.com", "account@qq.com", "account@qq.com", ]
def delShareFile():
# 删除共享文件夹里的备份文件
# 该文件夹路径为z:\\backup,里面均是压缩文件包
# 故,删除策略为反向排序,取文件的修改时间作为排序的关键字处理
# 删除时,保留最新的3个文件
files = [os.path.join(ShareDir, x) for x in os.listdir(ShareDir)]
if len(files) > 2:
sorted(files, key = lambda file:os.stat(file).st_mtime, reverse = True)
DelFiles = files[:-2]
for nfile in DelFiles:
os.remove(nfile) def delLocalFile():
# 删除本地文件夹里的备份文件
# 该文件夹路径为当前脚本所在路径,里面均是压缩文件包
# 故,删除策略为反向排序,取文件的修改时间作为排序的关键字处理
# 删除时,保留最新的1个文件(不删除该文件的目的是,避免误操作的文件丢失,同时,为后续操作保留一个缓存文件)
files = [os.path.join(os.getcwd(), x) for x in os.listdir(".") if "svn_backup" in x]
if len(files) > 1:
sorted(files, key = lambda file:os.stat(file).st_mtime, reverse = True)
DelFiles = files[:-1]
for nfile in DelFiles:
os.remove(nfile) def addFile(tf, files, root):
# 往压缩包里面添加文件,在添加时,均处理过文件的地址,添加了替换的replace方法的目的是相对路径时,避免出现多余的符号
st = time.time()
length = len(files)
for ids, nfile in enumerate(files):
if time.time() - st >= 3:
print "\radding file at root [%s]: [%s / %s], package is [%s MB]" % (root, ids, length, os.stat(tarPackage).st_size / (1024 * 1024))
st = time.time()
fp = os.path.join(root, nfile).replace(".\\","")
key = root.split("\\")
if len(key) > 1:
key = key[1]
if key not in ret:
ret[key] = os.stat(fp).st_size
else:
ret[key] += os.stat(fp).st_size
tf.add(fp) def checkDir(Names):
# 检测需要过滤得文件名或路径名,这里主要用来过滤svn主路径下的特殊文件夹名字
for nName in ignoreNames:
if nName not in Names:
pass
else:
return False
return True def maketar(dist, tar):
# 扫描缓存文件夹,对待处理的文件夹进行过滤,并调用添加方法,将待压缩文件添加到压缩包内
st = time.time()
cur = os.getcwd()
os.chdir(dist) for root, dir, files in os.walk("."):
if not checkDir(root):
continue
addFile(tar, files, root)
tar.close()
os.chdir(cur) def uploadFile(tar):
args = ["rsync","-avzPu", "--password-file=passwd.pd","<p.txt", "svn_backup_*", "cwRsync@127.0.0.0::mysvnbackup"]
os.system("".join(args))
#p = subprocess.Popen(args, stdin = subprocess.PIPE, stdout = subprocess.PIPE, stderr = subprocess.PIPE, shell = True)
#print p.communicate()[1]
#print p.stderr.read() def getMailBody(rd):
msg = '<table border=""><tr><th>RootDirName</th><th>PackageSize</th></tr>' for nk in sorted(rd.items(), key = lambda pair: pair[1], reverse = True):
if nk[1] < 1024:
msg += '<tr><td>%s</td><td>%.2fByte</td></tr>' % (nk[0], float(nk[1]))
elif nk[1] < 1024 * 1024:
msg += '<tr><td>%s</td><td>%.2fKB</td></tr>' % (nk[0], float(nk[1]) / 1024)
elif nk[1] < 1024 * 1024 *1024:
msg += '<tr><td>%s</td><td>%.2fMB</td></tr>' % (nk[0], float(nk[1]) / ( 1024 * 1024 ))
else:
msg += '<tr><td>%s</td><td><font color="red">%.2fGB</font></td></tr>' % (nk[0], float(nk[1]) / ( 1024 * 1024 * 1024 )) msg+= '</table>'
return msg global ret
ret = {}
# 获取时间参数,用来评估多线程实现的模块的性能,暂时无用,详见makeTar_multipleThreads.py
st = time.time()
# 获取当前日期,用于生成压缩包的名字
ts = datetime.datetime.now().strftime("%Y-%m-%d")
mailTitle = mailTitle % ts
# 开始打包 print "start making package."
tarPackage = os.path.join(os.getcwd(), BackUp % ts)
tar = tarfile.open(tarPackage, "w:gz")
maketar(TargetDir, tar)
print "finished making package. used time - %s" % (time.time() - st)
# 分析文件夹状态,发送邮件
mailer = Mailer()
msg = getMailBody(ret)
for nmail in receivers:
mailer.send(nmail, mailTitle, msg)
print "send mail to ", nmail # 删除z盘的备份文件
delShareFile()
# 上传备份文件到z盘
shutil.copy(tarPackage, ShareDir)
uploadFile(tarPackage)
# 删除本地的文件
delLocalFile()

仅仅实现了过滤备份并不靠谱,因为svn里面的资源和版本其实仍然在,直接找到svn文件夹,删除文件当然也可以,但是会导致svn库里面出现空版本或其他问题,所以还是要利用svn本身的管理工具去处理。搜索了半天,发现了svndumpfilter,可以利用他的exclude指令去过滤文件,然后把过滤后的文件结构导入svn即可,但实际按网又介绍的又各种出错,一般都是什么错误的文件头,如下图

反复研究和google尝试(baidu查不到的只能找google了)后,终于确认下列的流程是可以操作的:

1. 使用svnadmin把整个要处理的svn库的项目导出来

命令为:svnadmin dump repos1 > repos1.dump

repos1 为你的对应库名,repos1.dump为导出的文件名,可以随意命名,只要自己记得。

2. 使用svndumpfilter exclude命令过滤项目中废弃的文件夹,可以填写多个文件路径,该命令是根据路径名字过滤的。

命令为:svndumpfilter exlude directory1 directory2 directory3 <repos1.dump> filtered-repos1.dump

如上,路径可以随意填写,但一定要正确存在,比如你导出的是/test/test1,你要过滤的是test1下面的test2,那么这里的directory1应该写为test1/test2,如果还有其他要一并过滤的,可以空格添加其他directory2,directory3即可。

注意,路径中如果包含有空格等,需要用双引号包起来。避免识别错误。

路径配置完成后,一定要用<>把之前第一步导出来的备份dump文件括起来,表示过滤是在该文件的结构中进行。

而最后一个filtered-repos1.dump文件就很好理解了,就是过滤出来的新的结构备份文件。

过滤后的效果如下图:

3. 之后再新建一个库,导进去即可,如果要继续使用原来的库名,将原来的库删除后重建,导入即可,导入命令用svnadmin load。

当然备份打包还可以用svn推荐的svnadmin dump或svnadmin hotcopy文件备份,但速度太慢,还是直接整体文件拷贝比较快,虽然不够合理,但如果选择完全没人操作的时间还是可以的,这样恢复也快。对于我们的项目来说,目前还是选用文件打包备份快点,也可以和运维那边的管理方式结合起来,省的麻烦。。

使用svndumpfilter exclude来清理svn库的废弃文件实现差别备份的更多相关文章

  1. SVN库迁移整理方法总结

    有时候需要从一台机器迁移svn存储库到另外一台机器,如果数据量非常大的话,没有好的方法是很不方便的,其实迁移svn跟迁移mysql差不多,也有导出导入的方案 以下是subversion官方推荐的备份方 ...

  2. SVN库迁移整理方法----官方推荐方式

    以下是subversion官方推荐的备份方式. 关闭所有运行的进程,并确认没有程序在访问存储库(如 httpd.svnserve 或本地用户在直接访问). 备份svn存储库 #压缩备份 svnadmi ...

  3. 彻底删除SVN版本库中部分文件或文件夹

    例:假设SVN库路径为E:/svn/project,库中的目录结构为 QA/Trunk Software/Tags/test.exe 删除Software/Tags/目录下的test.exe文件 操作 ...

  4. 在Eclipse中导入SVN库里的Maven项目

    长期使用Intellij 对于Eclipse的东西都生疏了... 做了个小教程说明Eclipse下导入Maven工程的步骤以备不时之需 1. 安装maven插件 a) 下载maven http://m ...

  5. SVN库实时同步设置

    为了安全起见,SVN服务器除了做定时全量备份和增量备份以外,如条件允许,可做实时备份. 这需要2台机器,一台是master server,另一台做mirror server.master做主服务,mi ...

  6. SVN库迁移过程总结

    一.背景:老SVN是安装在32位服务器上:现在64位服务器上安装了新版本SVN服务,所以需要将SVN从老服务器上迁移到新服务器上. 1.SVN Server下载:https://www.visuals ...

  7. SVN库迁移

    最后库迁移.机会主义的,在源库资源,然后上传到目标库,最后client更新url地址.的库被组长一眼识破,由于新库中没有大家的操作日志. 这次吸取上次的教训,用dump和load完毕SVN库迁移. 整 ...

  8. 通过重建清理SVN服务器无用目录,不丢失其他目录修改记录

    1.主要时有时间希望调整一些文件的目录结构,或者移除一个大量占用空间的文件节省服务器磁盘,但是又不希望调整后,对应的修改记录丢失.这时可以通过服务器目录重建实现. 2.重建后只是被排除掉的目录的修改记 ...

  9. 清理svn.bat

     @echo on  color 2f  mode con: cols=80 lines=25  @REM  @echo 正在清理SVN文件,请稍候......  @rem 循环删除当前目录及子目录下 ...

随机推荐

  1. Ubuntu+Apache+PHP+Mysql环境搭建(完整版)(转)

    http://www.2cto.com/os/201505/401588.html Ubuntu+Apache+PHP+Mysql环境搭建(完整版) 一.操作系统Ubuntu 14.04 64位,阿里 ...

  2. SDUT-2121_数据结构实验之链表六:有序链表的建立

    数据结构实验之链表六:有序链表的建立 Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description 输入N个无序的整数,建立一个有序链 ...

  3. @atcoder - AGC036F@ Square Constraints

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 给定一个整数 N,统计有多少个 0~2N-1 的排列 \(P_0 ...

  4. React Native声明属性和属性确认

    属性声明 因为用React Native创建的自定义组件可以复用, 我们开发过程中可能一个项目组有多个人同时开发,其他同事可能会用到我们自定义的组件, 但是他们使用的时候很容易忘记使用某些属性,这时候 ...

  5. Browse W3C's Open Source Software

    https://www.w3.org/Status.html Browse W3C's Open Source Software Amaya - a Web browser/editor First ...

  6. PHPstorm相关设置以及快捷键

    转自:http://blog.csdn.net/fenglailea/article/details/12166617 1.界面中文方框问题 Settings->Appearance中Theme ...

  7. 强连通分量-----Kosaraju

    芝士: 有向图强连通分量在有向图G中,如果两个顶点vi,vj间(vi>vj)有一条从vi到vj的有向路径,同时还有一条从vj到vi的有向路径,则称两个顶点强连通(strongly connect ...

  8. GPUtil是一个Python模块,使用nvidia-smi从NVIDA GPU获取GPU状态

    GPUtil是一个Python模块,使用nvidia-smi从NVIDA GPU获取GPU状态 一个Python模块,用于在Python中使用nvidia-smi以编程方式从NVIDA GPU获取GP ...

  9. ThinkPHP5.1接收post、get参数

    我们要先认识的是请求对象Request类 <?php//要用Request类 第一步就要引入他,才能在当前控制器上使用//知识点:use 与 namespace前面不可有空格等其他操作.name ...

  10. 2016.1.22 扩充临时表空间解决ora-01652错误

    今天运行一个复杂查询时报错ora-01652 无法通过128 扩展temp段, 网上说是临时表空间大小不够,运行了脚本调整临时表空间,问题解决 alter database tempfile '/ap ...