提供备份脚本的zc构建方法

iw.recipe.backup的Python项目详细描述


代码库:https://ingeniweb.svn.sourceforge.net/svnroot/ingeniweb/iw.recipe.backup/

Change history

trunk (2009-11-25)

  • xxx [Ingeniweb]

0.2.1 (2008-11-24)

  • added ‘base-path’ option [fdupre] if set, use it instead buildout-dir, really usefull if datas are stored in another place in the system (NAS, NFS mount…).

0.2.0 (2008-05-08)

  • added ‘archive-before-backup’ option. [tdesvenain] True by default. If set to 0, buildout is not backuped before a restore
  • added ‘include-folders’ option, that allows to limit backup on some directories [tdesvenain]
  • create backups dir if not exists [tdesvenain]
  • add format option instead of archive-root-name [gawel]
  • fixing test so it passes on all machines [tarek]

0.1.2 (2008-04-11)

  • Added the fs-location option, that allows doing a safe backup of a running Data.fs. [tarek]

0.1.1 (2008-03-21)

  • Added the exclude-folders option
  • Now asks a question before restoring. It is more a conveniency since everything is backed up in any case. [tarek]

0.1.0 (2008-03-12)

  • Initial implementation. [tarek]
  • Created recipe with ZopeSkel [Ingeniweb].

Detailed Documentation

Supported options

配方支持以下选项:

备份脚本名称
备份脚本的名称。默认值:备份
还原脚本名称
还原脚本的名称。默认值:还原
格式
存档的格式化名称。 默认为%(名称)s-%(年份)s-%(月份)s-%(日期)s-%(小时)s-%(分钟)s 其中name是节名
排除文件夹
要避免备份的文件夹的名称。相对于构建根。
包括文件夹
如果已设置,请仅备份这些文件夹。相对于构建根。
fs位置
如果给定,则指示文件系统存储的路径。 做备份时,食谱会仔细复制, 通过使用文件的事务级读取。 这意味着您可以不停地启动备份 Zope服务器。
目标文件夹
存储档案的文件夹。必需
日志文件
记录所有呼叫的文件。必需
还原前存档
如果未设置为0,请在还原之前执行完整备份
还原前提示
如果未设置为0,则在还原之前提示
基本路径
如果已设置,请根据实例路径备份此路径

Example usage

我们将从创建使用配方的构建开始:

>>> import os
>>> root =  os.path.split(sample_buildout)[0]
>>> if root == '':
...     root = '.'

让我们在构建中复制一个真实的data.fs:

>>> import shutil
>>> data_fs = os.path.join(test_dir, 'Data.fs')
>>> shutil.copyfile(data_fs, join(sample_buildout, 'Data.fs'))

>>> write('buildout.cfg',
... """
... [buildout]
... parts = backup
... index = http://pypi.python.org/simple
...
... [backup]
... recipe = iw.recipe.backup
...
... format = %(format)s
... target-folder = %(root)s
... log-file = %(root)s/backup.log
... fs-location = ${buildout:directory}/Data.fs
... """ % {'root': root, 'format':'%(name)s-%(year)s-%(month)s-%(day)s'})

让我们运行构建:

>>> null = system(buildout)

让我们看看备份脚本中的内容:

>>> print open(join(sample_buildout, 'bin', 'backup')).read()
#!...
<BLANKLINE>
import sys
sys.path[0:0] = [
  ...
  ]
<BLANKLINE>
import iw.recipe.backup.archive
<BLANKLINE>
if __name__ == '__main__':
    iw.recipe.backup.archive.archive_buildout(('/sample-buildout', '%(name)s-%(year)s-%(month)s-%(day)s', '..._TEST_', '/backup.log', [], [], '/sample-buildout/Data.fs', {'name': 'backup'}))
<BLANKLINE>

好的,让我们调用它来备份当前的构建:

>>> print system(join(sample_buildout, 'bin', 'backup'))
Starting the backup...
Archived in /backup-XXXX-XX-XX.tar.gz
...
<BLANKLINE>

我们还应该生成一个日志文件:

>>> print open(join(root, 'backup.log')).read()
20... Starting the backup...
20... INFO Archived in /backup-XXXX-XX-XX.tar.gz

我们还有一个还原功能:

>>> print system(join(sample_buildout, 'bin', 'restore'))
Usage: ...restore archive_name
<BLANKLINE>

让我们设置用户输入:

>>> from iw.recipe.backup.testing import set_input
>>> set_input('Y')

哦,对了,还原脚本采用存档的名称:

>>> import glob
>>> arc = glob.glob('%s/*.tar.gz' % root)[0]
>>> print system(join(sample_buildout, 'bin', 'restore %s' % arc))
Are you sure you want to restore ? Every data will be lost ! (y/N)  Y
Archiving current folder before restoring
Starting the backup...
Archived in /before-restore-XXXX-XX-XX-XX-XX.tar.gz
Starting the restore...
Archive restored in /sample-buildout
...
<BLANKLINE>

而restore总是在 它被应用,以确保不会丢失任何东西。

还有一件很重要的事情:确保档案和 日志文件不在构建中!:

>>> write('buildout.cfg',
... """
... [buildout]
... parts = backup
... index = http://pypi.python.org/simple
...
... [backup]
... recipe = iw.recipe.backup
...
... target-folder = %(root)s
... log-file = %(root)s/backup.log
... """ % {'root': sample_buildout})

>>> print system(buildout)
Uninstalling backup.
Installing backup.
While:
  Installing backup.
<BLANKLINE>
An internal error occured due to a bug in either zc.buildout or in a
recipe being used:
...
ValueError: Cannot backup within the buildout ! Check your values
<BLANKLINE>

一点清洁:

>>> import glob
>>> arc = glob.glob('%s/*.tar.gz' % root)
>>> for f in arc:
...     os.remove(f)

我们还可以将某些文件夹排除在存档之外:

>>> os.mkdir(join(sample_buildout, 'not'))
>>> open(join(sample_buildout, 'not', 'f'), 'w').write('me file')

>>> os.mkdir(join(sample_buildout, 'neh'))

>>> write('buildout.cfg',
... """
... [buildout]
... parts = backup
... index = http://pypi.python.org/simple
...
... [backup]
... recipe = iw.recipe.backup
...
... target-folder = %(root)s
... log-file = %(root)s/backup.log
... fs-location = ${buildout:directory}/Data.fs
... exclude-folders =
...     %(sample_buildout)s/not
...     %(sample_buildout)s/neh
... """ % {'root': root, 'sample_buildout': sample_buildout})

再次运行构建:

>>> print system(buildout+' -D')
Installing backup.
Generated script '...backup'.
Generated script '...restore'.
<BLANKLINE>

让我们备份:

>>> print system(join(sample_buildout, 'bin', 'backup'))
Starting the backup...
Archived in /backup-XXXX-XX-XX-XX-XX.tar.gz
...
<BLANKLINE>

让我们删除文件夹和data.fs:

>>> import shutil
>>> shutil.rmtree(join(sample_buildout, 'not'))
>>> os.rmdir(join(sample_buildout, 'neh'))
>>> os.remove(join(sample_buildout, 'Data.fs'))

让我们还原:

>>> arc = glob.glob('%s/*.tar.gz' % root)[0]
>>> print system(join(sample_buildout, 'bin', 'restore %s' % arc))
Are you sure you want to restore ? Every data will be lost ! (y/N)  Y
...
<BLANKLINE>

并确保not文件夹未返回!

>>> os.path.exists(join(sample_buildout, 'not'))
False
>>> os.path.exists(join(sample_buildout, 'neh'))
False

data.fs又回来了,所以我们没事了:

>>> os.path.exists(join(sample_buildout, 'Data.fs'))
True

我们还可以限制某些文件夹的存档

>>> os.mkdir(join(sample_buildout, 'not'))
>>> open(join(sample_buildout, 'not', 'f'), 'w').write('me file')

>>> os.mkdir(join(sample_buildout, 'neh'))
>>> open(join(sample_buildout, 'neh', 'f'), 'w').write('me file')

>>> os.mkdir(join(sample_buildout, 'neh/not'))
>>> open(join(sample_buildout, 'neh/not', 'f'), 'w').write('me file')

>>> write('buildout.cfg',
... """
... [buildout]
... parts = backup
... index = http://pypi.python.org/simple
...
... [backup]
... recipe = iw.recipe.backup
...
... target-folder = %(root)s
... log-file = %(root)s/backup.log
... fs-location = ${buildout:directory}/Data.fs
... exclude-folders =
...     %(sample_buildout)s/not
...     %(sample_buildout)s/neh/not
... include-folders =
...     %(sample_buildout)s/neh
... prompt-before-restore = 0
... archive-before-restore = 0
... """ % {'root': root, 'sample_buildout': sample_buildout})

再次运行构建:

>>> print system(buildout+' -D')
Uninstalling backup.
Installing backup.
Generated script '...backup'.
Generated script '...restore'.
<BLANKLINE>

让我们看看备份脚本中的内容:

>>> print open(join(sample_buildout, 'bin', 'backup')).read()
#!...
<BLANKLINE>
import sys
sys.path[0:0] = [
  ...
  ]
<BLANKLINE>
import iw.recipe.backup.archive
<BLANKLINE>
if __name__ == '__main__':
    iw.recipe.backup.archive.archive_buildout(('/sample-buildout', '...', '..._TEST_', '/backup.log', ['/sample-buildout/not', '/sample-buildout/neh/not'], ['/sample-buildout/neh'], '/sample-buildout/Data.fs', {'name': 'backup'}))
<BLANKLINE>

让我们备份:

>>> print system(join(sample_buildout, 'bin', 'backup'))
Starting the backup...
Archived in /backup-XXXX-XX-XX-XX-XX.tar.gz
<BLANKLINE>

让我们删除文件夹和data.fs:

>>> import shutil
>>> shutil.rmtree(join(sample_buildout, 'not'))
>>> shutil.rmtree(join(sample_buildout, 'neh'))
>>> os.remove(join(sample_buildout, 'Data.fs'))

让我们还原:

>>> arc = glob.glob('%s/*.tar.gz' % root)[0]
>>> rest = os.popen(join(sample_buildout, 'bin', 'restore %s' % arc))
并确保not文件夹和“neh/not”未返回,neh已返回!
>>> os.path.exists(join(sample_buildout, 'not'))
False
>>> os.path.exists(join(sample_buildout, 'neh/not'))
False
>>> os.path.exists(join(sample_buildout, 'neh'))
True

Contributors

IngeniWeb,作者

欢迎加入QQ群-->: 979659372 Python中文网_新手群

推荐PyPI第三方库


热门话题
java Log4j:运行服务器日志时发出警告   ssl与Java通信到TLSEncypted CUPS打印服务器   Guice Java提供的方法没有已知的依赖关系?   java Android:EditText的默认文本大小是多少?   更正错误字符串的Java异常   string Java如何从来自多个源的数据推断类型   从路径错误创建java文件   java获取不同类安卓中切换按钮的状态   java扩展AnyVal和AnyRef的对象的内存分配有什么不同   java如何从callable(即runnable)获取类名   java Hornetq大量消息填满了磁盘空间   用java从excel中读取一行的多列?   java不使用JAXB将映射转换为XML   java将多个图像与一个图像进行比较   当X扩展Y时,javax不适用于参数Y   运行时jar文件中未显示java Python输出   JavaSpringMVC3:定义自己的DatatypeBinding   java从fragment类调用activity函数给出了NPE   java在时区、日历和SimpleDataFormat方面存在奇怪的问题