下面的脚本是在windows SVN的备份策略,采用的是hotcopy的方法

方案一:

1.先创建一个fullBackup的脚本;fullBackup.bat

echo off

rem Subversion的安装目录
set SVN_HOME="D:\Program Files\Subversion\bin" rem 所有版本库的父目录
set SVN_ROOT=D:\svnserver rem 备份的目录
set BACKUP_SVN_ROOT=D:\backupsvn\fullbackup
set BACKUP_DIRECTORY=%BACKUP_SVN_ROOT%\%date:~,%%date:~,%%date:~,%
set LOG_FILE=fullbackup-%date:~,%%date:~,%%date:~,%.log
if exist %BACKUP_DIRECTORY% rd /s/q %BACKUP_DIRECTORY%
echo 建立备份目录%BACKUP_DIRECTORY%>>%SVN_ROOT%\%LOG_FILE%
mkdir %BACKUP_DIRECTORY% mkdir %BACKUP_DIRECTORY%\conf
xcopy %SVN_ROOT%\conf %BACKUP_DIRECTORY%\conf
echo %SVN_ROOT%\conf成功备份到了%BACKUP_DIRECTORY%\conf>>%SVN_ROOT%\%LOG_FILE% rem 验证目录是否为版本库,如果是则取出名称备份
for /r %SVN_ROOT% %%I in (.) do @if exist "%%I\conf\svnserve.conf" hotcopy.bat "%%~fI" %%~nI

2.在创建一个热备脚本,hotcopy.bat

@echo 正在备份版本库%……
@%SVN_HOME%\svnadmin hotcopy % %BACKUP_DIRECTORY%\%
@echo 版本库%1成功备份到了%!
echo 版本库%1成功备份到了%BACKUP_DIRECTORY%\%>>%SVN_ROOT%\%LOG_FILE%

3.定期删除一个月之前的备份,delSVN.bat

echo on
rem 需要删除的SVN备份目录
set BACKUPSVN_ROOT="D:\backupsvn\fullbackup"
rem 正在删除30天前的备份版本库。。。
forfiles /p %BACKUPSVN_ROOT% /s /m * /d - /c "cmd /c del /s/q @path"
rem 删除空文件夹
dir /ad/b/s %BACKUPSVN_ROOT% |sort /r >f:\kill.txt
For /f "tokens=*" %%i in (f:\kill.txt) DO rd "%%i"
del f:\kill.txt

4.将这三个脚本放到一个目录下,点击fullBackup.bat就会在备份目录下生成YYmmdd/版本库。但是遗憾的是我将这个fullBackup放到任务计划程序中执行,下面的一个hotcopy.bat总是没执行成功,我已放弃。

方案二:

写一个备份脚本 hotcopy.bat

svnadmin hotcopy D:\Repositories\root F:\SVN\fullbackup\%date:~,%%date:~,%%date:~,%

放到任务计划执行就OK了,再结合delSVN.bat就可以达到定期删除的目的。

方案三,用官方提供的备份脚本

可以定制备份几次,是否压缩

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# hot-backup.py: perform a "hot" backup of a Subversion repository
# and clean any old Berkeley DB logfiles after the
# backup completes, if the repository backend is
# Berkeley DB.
#
# Subversion is a tool for revision control.
# See http://subversion.apache.org for more information.
#
# ====================================================================
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
# ==================================================================== # $HeadURL: https://svn.apache.org/repos/asf/subversion/branches/1.10.x/tools/backup/hot-backup.py.in $
# $LastChangedDate: 2015-12-21 15:02:31 +0000 (Mon, 21 Dec 2015) $
# $LastChangedBy: danielsh $
# $LastChangedRevision: 1721179 $ ###################################################################### import sys, os, getopt, stat, re, time, shutil, subprocess ######################################################################
# Global Settings # Path to svnlook utility
svnlook = r"@SVN_BINDIR@/svnlook" # Path to svnadmin utility
svnadmin = r"@SVN_BINDIR@/svnadmin" # Default number of backups to keep around (0 for "keep them all")
num_backups = int(os.environ.get("SVN_HOTBACKUP_BACKUPS_NUMBER", 64)) # Archive types/extensions
archive_map = {
'gz' : ".tar.gz",
'bz2' : ".tar.bz2",
'zip' : ".zip",
'zip64' : ".zip"
} # Chmod recursively on a whole subtree
def chmod_tree(path, mode, mask):
for dirpath, dirs, files in os.walk(path):
for name in dirs + files:
fullname = os.path.join(dirpath, name)
if not os.path.islink(fullname):
new_mode = (os.stat(fullname)[stat.ST_MODE] & ~mask) | mode
os.chmod(fullname, new_mode) # For clearing away read-only directories
def safe_rmtree(dirname, retry=0):
"Remove the tree at DIRNAME, making it writable first"
def rmtree(dirname):
chmod_tree(dirname, 0o666, 0o666)
shutil.rmtree(dirname) if not os.path.exists(dirname):
return if retry:
for delay in (0.5, 1, 2, 4):
try:
rmtree(dirname)
break
except:
time.sleep(delay)
else:
rmtree(dirname)
else:
rmtree(dirname) ######################################################################
# Command line arguments def usage(out = sys.stdout):
scriptname = os.path.basename(sys.argv[0])
out.write(
"""USAGE: %s [OPTIONS] REPOS_PATH BACKUP_PATH Create a backup of the repository at REPOS_PATH in a subdirectory of
the BACKUP_PATH location, named after the youngest revision. Options:
--archive-type=FMT Create an archive of the backup. FMT can be one of:
bz2 : Creates a bzip2 compressed tar file.
gz : Creates a gzip compressed tar file.
zip : Creates a compressed zip file.
zip64: Creates a zip64 file (can be > 2GB).
--num-backups=N Number of prior backups to keep around (0 to keep all).
--verify Verify the backup.
--help -h Print this help message and exit. """ % (scriptname,)) try:
opts, args = getopt.gnu_getopt(sys.argv[1:], "h?", ["archive-type=",
"num-backups=",
"verify",
"help"])
except getopt.GetoptError as e:
sys.stderr.write("ERROR: %s\n\n" % e)
sys.stderr.flush()
usage(sys.stderr)
sys.exit(2) archive_type = None
verify_copy = False for o, a in opts:
if o == "--archive-type":
archive_type = a
elif o == "--num-backups":
num_backups = int(a)
elif o == "--verify":
verify_copy = True
elif o in ("-h", "--help", "-?"):
usage()
sys.exit() if archive_type not in (None, 'bz2', 'gz', 'zip', 'zip64'):
sys.stderr.write("ERROR: Bad --archive-type\n")
usage(sys.stderr)
sys.exit(2) if len(args) != 2:
sys.stderr.write("ERROR: only two arguments allowed.\n\n")
sys.stderr.flush()
usage(sys.stderr)
sys.exit(2) # Path to repository
repo_dir = args[0]
repo = os.path.basename(os.path.abspath(repo_dir)) # Where to store the repository backup. The backup will be placed in
# a *subdirectory* of this location, named after the youngest
# revision.
backup_dir = args[1] # Added to the filename regexp, set when using --archive-type.
ext_re = "" # Do we want to create an archive of the backup
if archive_type:
if archive_type in archive_map:
# Additionally find files with the archive extension.
ext_re = "(" + re.escape(archive_map[archive_type]) + ")?"
else:
sys.stderr.write("Unknown archive type '%s'.\n\n\n" % archive_type)
sys.stderr.flush()
usage(sys.stderr)
sys.exit(2) ######################################################################
# Helper functions def comparator(a, b):
# We pass in filenames so there is never a case where they are equal.
regexp = re.compile("-(?P<revision>[0-9]+)(-(?P<increment>[0-9]+))?" +
ext_re + "$")
matcha = regexp.search(a)
matchb = regexp.search(b)
reva = int(matcha.groupdict()['revision'])
revb = int(matchb.groupdict()['revision'])
if (reva < revb):
return -1
elif (reva > revb):
return 1
else:
inca = matcha.groupdict()['increment']
incb = matchb.groupdict()['increment']
if not inca:
return -1
elif not incb:
return 1;
elif (int(inca) < int(incb)):
return -1
else:
return 1 def get_youngest_revision():
"""Examine the repository REPO_DIR using the svnlook binary
specified by SVNLOOK, and return the youngest revision.""" p = subprocess.Popen([svnlook, 'youngest', '--', repo_dir],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
infile, outfile, errfile = p.stdin, p.stdout, p.stderr stdout_lines = outfile.readlines()
stderr_lines = errfile.readlines()
outfile.close()
infile.close()
errfile.close() if stderr_lines:
raise Exception("Unable to find the youngest revision for repository '%s'"
": %s" % (repo_dir, stderr_lines[0].rstrip())) return stdout_lines[0].strip() ######################################################################
# Main print("Beginning hot backup of '"+ repo_dir + "'.") ### Step 1: get the youngest revision. try:
youngest = get_youngest_revision()
except Exception as e:
sys.stderr.write("%s\n" % e)
sys.stderr.flush()
sys.exit(1) print("Youngest revision is %s" % youngest) ### Step 2: Find next available backup path backup_subdir = os.path.join(backup_dir, repo + "-" + youngest) # If there is already a backup of this revision, then append the
# next highest increment to the path. We still need to do a backup
# because the repository might have changed despite no new revision
# having been created. We find the highest increment and add one
# rather than start from 1 and increment because the starting
# increments may have already been removed due to num_backups. regexp = re.compile("^" + re.escape(repo) + "-" + re.escape(youngest) +
"(-(?P<increment>[0-9]+))?" + ext_re + "$")
directory_list = os.listdir(backup_dir)
young_list = [x for x in directory_list if regexp.search(x)]
if young_list:
young_list.sort(comparator)
increment = regexp.search(young_list.pop()).groupdict()['increment']
if increment:
backup_subdir = os.path.join(backup_dir, repo + "-" + youngest + "-"
+ str(int(increment) + 1))
else:
backup_subdir = os.path.join(backup_dir, repo + "-" + youngest + "-1") ### Step 3: Ask subversion to make a hot copy of a repository.
### copied last. print("Backing up repository to '" + backup_subdir + "'...")
err_code = subprocess.call([svnadmin, "hotcopy", "--clean-logs",
'--', repo_dir, backup_subdir])
if err_code != 0:
sys.stderr.write("Unable to backup the repository.\n")
sys.stderr.flush()
sys.exit(err_code)
else:
print("Done.") ### Step 4: Verify the hotcopy
if verify_copy:
print("Verifying backup...")
err_code = subprocess.call([svnadmin, "verify", "--quiet", '--', backup_subdir])
if err_code != 0:
sys.stderr.write("Backup verification failed.\n")
sys.stderr.flush()
sys.exit(err_code)
else:
print("Done.") ### Step 5: Make an archive of the backup if required.
if archive_type:
archive_path = backup_subdir + archive_map[archive_type]
err_msg = "" print("Archiving backup to '" + archive_path + "'...")
if archive_type == 'gz' or archive_type == 'bz2':
try:
import tarfile
tar = tarfile.open(archive_path, 'w:' + archive_type)
tar.add(backup_subdir, os.path.basename(backup_subdir))
tar.close()
except ImportError as e:
err_msg = "Import failed: " + str(e)
err_code = -2
except tarfile.TarError as e:
err_msg = "Tar failed: " + str(e)
err_code = -3 elif archive_type == 'zip' or archive_type == 'zip64':
try:
import zipfile def add_to_zip(zp, root, dirname, names):
root = os.path.join(root, '') for file in names:
path = os.path.join(dirname, file)
if os.path.isfile(path):
zp.write(path, path[len(root):])
elif os.path.isdir(path) and os.path.islink(path):
for dirpath, dirs, files in os.walk(path):
add_to_zip(zp, path, dirpath, dirs + files) zp = zipfile.ZipFile(archive_path, 'w', zipfile.ZIP_DEFLATED, archive_type == 'zip64')
for dirpath, dirs, files in os.walk(backup_subdir):
add_to_zip(zp, backup_dir, dirpath, dirs + files)
zp.close()
except ImportError as e:
err_msg = "Import failed: " + str(e)
err_code = -4
except zipfile.error as e:
err_msg = "Zip failed: " + str(e)
err_code = -5 if err_code != 0:
sys.stderr.write("Unable to create an archive for the backup.\n%s\n" % err_msg)
sys.stderr.flush()
sys.exit(err_code)
else:
print("Archive created, removing backup '" + backup_subdir + "'...")
safe_rmtree(backup_subdir, 1) ### Step 6: finally, remove all repository backups other than the last
### NUM_BACKUPS. if num_backups > 0:
regexp = re.compile("^" + re.escape(repo) + "-[0-9]+(-[0-9]+)?" + ext_re + "$")
directory_list = os.listdir(backup_dir)
old_list = [x for x in directory_list if regexp.search(x)]
old_list.sort(comparator)
del old_list[max(0,len(old_list)-num_backups):]
for item in old_list:
old_backup_item = os.path.join(backup_dir, item)
print("Removing old backup: " + old_backup_item)
if os.path.isdir(old_backup_item):
safe_rmtree(old_backup_item, 1)
else:
os.remove(old_backup_item)

  

在windows上自动备份SVN版本库及定时删除的更多相关文章

  1. 批量自动更新SVN版本库 - Windows

    开发过程中每天都要从SVN代码库里一个一个的update各个项目代码,不仅效率实在是低,也不符合程序员的"懒"精神,由于是在Windows环境做开发,自然就想到了使用bat来实现自 ...

  2. 工作随笔——使用svnsync实时备份SVN版本库

    前段时间把SVN版本库从win迁移到了Linux上,没隔几天那台win的磁盘就严重坏道了....这TMD什么运气! 花费了点时间研究了下svn自己的同步工具.写个日志记录下. 注意:svnsync要求 ...

  3. 使用svnsync实时备份SVN版本库

    前段时间把SVN版本库从win迁移到了Linux上,没隔几天那台win的磁盘就严重坏道了....这TMD什么运气! 花费了点时间研究了下svn自己的同步工具.写个日志记录下. 注意:svnsync要求 ...

  4. 用svnsync 同步备份 svn 版本库 从一台服务器到另一台服务器

    如用svnsync 同步备份两台机器的svn .(就以linux服务器到windows服务器为例子) 要同步的项目名称:source_svn svn 版本库1 .4 以上 源目录:           ...

  5. 在ubuntu上建立多svn版本库

    http://lucane.iteye.com/blog/857486 mkdir ~/dev/repository svnadmin create ~/dev/repository/a svnadm ...

  6. svn版本库更新后自动同步到www

    注意:www目录一定要用SVN服务器 checkout出Repositories的代码 步骤: (1)新建www根目录 mkdir -p /data/www/lehuo (2)在www根目录下检出(c ...

  7. SVN版本库备份和恢复

    1.版本库备份 1.1.svnadmin dump方式备份 此方法借助的是Subversion官网推荐的svnadmin dump备份方式,它的优点是比较灵活,既可以进行全量备份又可以进行增量备份,并 ...

  8. CentOS 7 环境下部署 SVN 并实现自动更新(版本库放在Tomcat下)

    1.安装 SVN 1.1先检查是否有安装 svn rpm -qa subversion #没有什么显示就说明没有安装过yum remove subversion #如果有安装就运行删除老版本yum i ...

  9. linux 创建svn版本库,并在svn上配置checkstyle做代码风格检查

    一.创建SVN版本库 1.安装svn服务器 yum install subversion 2.查看版本 svnserve --version 3.建立SVN版本库目录(即你的SVN服务器里面的文件存放 ...

随机推荐

  1. Java Callable并发编程模板

    submit方法会产生Future对象,它用Callable返回结果的特定类型进行了参数化,可以用isDone()的方法来查询Future是否已经完成.当任务完成是,它具有一个结果,可以调用get() ...

  2. jfinal视频目录

    目录-----------------------------------------------------------第一章 简介第二章 JFine2.0 maven demo第三章番外篇 JFi ...

  3. JavaScript高级 面向对象(5)--最简单的继承方式,混入mix

    说明(2017.3.30): 1. 最简单的继承方式,混入mix <!DOCTYPE html> <html lang="en"> <head> ...

  4. R 画structure图

    id percent  k1_B04_WL-1.fs_1   0.021 k31_B04_WL-1.fs_1   0.624 k21_B04_WL-1.fs_1   0.355 k1 K=3  数据输 ...

  5. 服务器响应慢的分析与解决(Linux服务器)

    一.分析思路 1.排除本机自身原因 2.服务器性能分析 3.项目本身分析(不详细说) 4.虚拟机分析 5.数据库分析 二.详细分析方法 1.排除本机自身原因 可以使用站长工具测试网站速度. 2.服务器 ...

  6. Android——进度条控制图片透明度

    xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android= ...

  7. __attribute__((weak, alias())))

    参考gcc的reference: 弱符号: 若两个或两个以上全局符号(函数或变量名)名字一样,而其中之一声明为weak symbol(弱符号),则这些全局符号不会引发重定义错误.链接器会忽略弱符号,去 ...

  8. UI领域中常常听见的''modal''到底是什么?

    模态窗口其实就是个弹窗.... 问题总结 用户需要采取操作或取消覆盖,直到他可以继续与原始页面进行交互, 这是最原始的modal定义, 本质上是页面在时间维度上的中断系统: 来自wiki百科: Mod ...

  9. 七、CentOS 6.5 下 Nginx的反向代理和负载均衡的实现

    CentOS 6.5 下 Nginx的反向代理和负载均衡的实现 * 修复上面文章的问题: 复制出一个tomcat2之后,修改service.xml文件时,要修改三个端口: 1. <!-- 800 ...

  10. KBEngine.executeRawDatabaseCommand使用

    先贴一段官方的API介绍: def executeRawDatabaseCommand( command, callback, threadID, dbInterfaceName ): 功能说明: 这 ...