警告:本文充斥着大量机翻
bup: It backs things up
bup 是一个备份程序。它是“backup”的缩写。难以置信的是,这竟然是第一个被命名位“bup”的开源程序。
尽管bup的名字不起眼,但它很酷。为了让你知道这有多酷,我写了这首诗:
1 | Bup is teh awesome |
嗯……这样有帮助吗?也许散文更有用。
bup太棒了
bup有一些其它备份软件没有的优点:
它使用滚动校验算法(类似于rsync),将大文件分割成若干块。这样做的好处是,你可以增量备份巨大的虚拟机(VM)磁盘镜像、数据库和XML文件——即使它们通常都在一个巨大的文件中,也不会因为多次备份消耗大量的磁盘空间
它使用git(开源版本控制系统)的packfile格式,这样一来,即使你不喜欢bup的用户界面,也可以通过别的方式访问存储的数据。
与git不同,它直接写packfiles(没有单独的垃圾收集/重新打包阶段)。即使是巨大的数据量,它依旧能保持很高的效率。bup改进的索引格式也允许你追踪比git更多的文件名(数百万),并追踪更多的对象(数百或数千GB)。
数据“自动”在增量备份之间共享,而无需了解哪个备份是基于哪个备份——即使备份是由两台互不关联的计算机制成。您只需使用bup进行备份,它就能以最小的数据量建立增量备份。
你可以直接备份到一个远程bup服务器,从而不消耗本地磁盘空间。如果你的备份进程在中途被打断了,下一次启动将会接着中断的地方继续。部署一个bup服务器也十分简单:只需要在一个有着ssh访问权限的设备安装bup。
Bup可以拥有“PAR2”冗余,即使磁盘有未被发现的损坏,也可以恢复已损坏的内容。
增量备份时,你无须担心每次都会保存一份完整的备份;_增量_备份只会在第一次进行完整备份,仅仅消耗少量的磁盘空间。
你可以将你的仓库挂在位一个FUSE文件系统进行访问,或者通过Samba导出。
它时用python写的(有些部分用了C使得它更高效),因此,你很容易对它进行拓展和维护。
你也可能想避免使用bup
它远没有像tar那样经过良好的测试,它更有可能吃掉你的数据。它还缺少一些关键性的功能,但它一直在被完善。
它需要Python 3.7或更新版本(或2.7稍长),C语言编译器,以及1.5.6或更新版本的git。如果你希望fsck能够生成从某些损坏的类型中恢复的信息,它也需要par2。虽然Python 2.7仍被支持,但请做好升级计划。Python 2的上游支持在2020-01-01结束,我们也将会放弃支持。
它现在只能在Linux,FreeBSD,NetBSD,OS X 10.4+,Solaris,或者Windows(with Cygwin, and WSL)上运行。欢迎提供在其它平台运行的补丁。
直到被解决前,如果bup运行在Python 3环境下,在命令行中使用某些不寻常的参数时,bup会崩溃。glibc bug
其它任何在“这太蠢了”中的项目。
新版本带来的显著变化
- Changes in 0.32 as compared to 0.31
- Changes in 0.31 as compared to 0.30.1
- Changes in 0.30.1 as compared to 0.30
- Changes in 0.30 as compared to 0.29.3
- Changes in 0.29.3 as compared to 0.29.2
- Changes in 0.29.2 as compared to 0.29.1
- Changes in 0.29.1 as compared to 0.29
- Changes in 0.29 as compared to 0.28.1
- Changes in 0.28.1 as compared to 0.28
- Changes in 0.28 as compared to 0.27.1
- Changes in 0.27.1 as compared to 0.27
测试状态
branch
Debian
FreeBSD
macOS
master
0.30.x
0.29.x
开始
从源码开始
使用git获取bup源码:
1
git clone https://github.com/bup/bup
如果你想帮助开发,你应该留在当前的主分支上。但是如果您只想使用bup,请查看最新的稳定版本:
1
git checkout 0.32
你可以在这里找到最新的稳定版:https://github.com/bup/bup/releases。
安装最新的python库(包括开发库)。
在最近的Debian/Ubuntu版本上,使用以下命令(以root用户身份运行):
1
apt-get build-dep bup
否则,请尝试以下命令:
1
2
3
4
5
6
7
8
9apt-get install python3.7-dev python3-fuse
apt-get install python3-pyxattr python3-pytest
apt-get install python3-distutils
apt-get install pkg-config linux-libc-dev libacl1-dev
apt-get install gcc make acl attr rsync
apt-get isntall python3-pytest-xdist # 可选(平行测试)
apt-get install par2 # 可选(纠错)
apt-get install libreadline-dev # 可选 (bup ftp)
apt-get install python3-tornado # 可选 (bup web)或者,如果您还不能迁移到Python 3(请尽快迁移):
1
2
3
4
5
6
7
8apt-get install python2.7-dev python-fuse
apt-get install python-pyxattr python-pytest
apt-get install pkg-config linux-libc-dev libacl1-dev
apt-get install gcc make acl attr rsync
apt-get isntall python-pytest-xdist # 可选(平行测试)
apt-get install par2 # 可选(纠错)
apt-get install libreadline-dev # 可选(bup ftp)
apt-get install python-tornado # 可选(bup web)在CentOS上(至少对于CentOS 6),使用以下命令(以root用户身份运行):
1
2
3
4
5
6yum groupinstall "Development Tools"
yum install python2 python2-devel libacl-devel pylibacl
yum install fuse-python pyxattr
yum install perl-Time-HiRes
yum install readline-devel # 可选(bup ftp)
yum install python-tornado # 可选(bup web)除了默认的CentOS仓库之外,您可能还需要添加RPMForge(fuse python)和EPEL(pyxattr)。
在Cygwin上,安装python、make、rsync和gcc4。
如果您想在没有tornado软件包的系统上使用可选的bup web服务器,您可能需要尝试以下命令:
1
pip install tornado
构建:
1
make
运行测试:
1
make long-check
或者,如果你想快一点:
1
make check
如果安装了Python XDist模块,那么通过添加
-j
选项,你可能可以更快地运行测试(有关更多信息,请参阅./HACKING):1
make -j check
测试应该通过。如果没有通过,请发送电子邮件给bup-list@googlegroups.com。如果当前工作目录路径上有符号链接,测试可能会失败,但你可以在测试之前使用以下命令可以避免这个问题:
1
cd "$(pwd -P)"
您可以通过
make install
安装bup,并使用DESTDIR和PREFIX覆盖默认目标。文件通常安装到
$DESTDIR/$PREFIX
,其中DESTDIR默认为空,PREFIX默认为/usr/local
。因此,如果要将bup安装到/opt/bup
,可以执行以下命令:1
make install DESTDIR=/opt/bup PREFIX=''
bup使用的Python版本由
./configure
选择的python-config
程序决定,该程序将搜索合理的版本,除非在环境中设置了bup_Python_config
。你可以通过configure输出或检查config/config.var/bup-Python-config
来查看选择了哪个Python可执行文件,你也可以通过重新运行./configure
来更改选择。
从二进制包开始
已知bup的二进制软件包是为以下操作系统构建的:
- Debian: http://packages.debian.org/search?searchon=names&keywords=bup
- Ubuntu: http://packages.ubuntu.com/search?searchon=names&keywords=bup
- pkgsrc (NetBSD, Dragonfly, and others) http://pkgsrc.se/sysutils/bup http://cvsweb.netbsd.org/bsdweb.cgi/pkgsrc/sysutils/bup/
- Arch Linux: https://www.archlinux.org/packages/?sort=&q=bup
- Fedora: https://apps.fedoraproject.org/packages/bup
- macOS (Homebrew): https://formulae.brew.sh/formula/bup
使用bup
获取任何bup命令的帮助:
1
2
3
4
5
6bup help
bup help init
bup help index
bup help save
bup help restore
...初始化默认的BUP_DIR(
~/.BUP
你可以通过bup -d DIR…
设定BUP_DIR
环境变量):1
bup init
创建一份本地备份(
-v
或-vv
能够增加可读性):1
2bup index /etc
bup save -n local-etc /etc恢复备份到
./dest
:1
2bup restore -C ./dest local-etc/latest/etc
ls -l dest/etc查看你的备份占用了多少磁盘空间:
1
du -s ~/.bup
再次进行备份(与上一次完全相同;请注意,你不必指定此备份为增量备份,它会自动进行增量备份):
1
2bup index /etc
bup save -n local-etc /etc看看在第一次备份的基础上第二次备份使用了多少磁盘空间:
1
du -s ~/.bup
获取已有的备份:
1
bup ls local-etc
恢复你的第一次备份:
1
bup restore -C ./dest-2 local-etc/2013-11-23-11195/etc
备份到远程服务器需要远程服务器上能够执行
bup
命令(包含在环境变量PATH
中。/etc/profile
,etc/environment
,~/.profile
,~/.bashrc
),并且能够通过ssh连接远程服务器。 将SERVERNAME
替换为实际的服务器名:1
2
3bup init -r SERVERNAME:path/to/remote-bup-dir
bup index /etc
bup save -r SERVERNAME:path/to/remote-bup-dir -n local-etc /etc备份到远程服务器的
~/.bup
:1
2bup index /etc
bup save -r SERVER: -n local-etc /etc查看远程服务器中已有的备份:
1
bup ls -r SERVER:
将远程备份恢复到
./dest
:1
2bup restore -r SERVER: -C ./dest local-etc/latest/etc
ls -l dest/etc保护你的备份不受死亡射线的伤害(好吧,更可能是偶尔出现的坏磁盘块)。这会写入所有现有数据的奇偶校验信息(目前通过par2),以便bup能够从一定数量的存储库损坏中恢复:
1
bup fsck -g
使用split/join而不是index/save/restore。尝试使用tar进行本地备份:
1
tar -cvf - /etc bup split -n local-etc -vv
尝试恢复tarball:
1
bup join local-etc tar -tf -
查看你的备份占用了多少磁盘空间:
1
du -s ~/.bup
再次创建tar备份:
1
tar -cvf - /etc bup split -n local-etc -vv
看看在第一次备份的基础上第二次备份使用了多少磁盘空间:
1
du -s ~/.bup
恢复第一次备份(
~1
是git符号,表示比最新版本旧的版本):1
bup join local-etc~1 tar -tf -
查看基于split的备份:
1
GIT_DIR=~/.bup git log local-etc
将tar存档保存到远程服务器(不使用
tar-z
以消除重复数据):1
tar -cvf - /etc bup split -r SERVERNAME: -n local-etc -vv
从远程tar存档恢复:
1
bup join -r SERVERNAME: local-etc tar -tf -
就这些!
关于FreeBSD
FreeBSD的
make
命令不同于bup的Makefile
。为了编译代码、运行测试并安装bup,你需要从名为gmake
的端口安装GNU Make
,然后使用其中的可执行文件。(即使用gmake test
运行bup的测试套件)Python的开发头会自动安装在
python
端口上,因此无需单独安装。要使用
bup fuse
命令,需要从sysutils
部分的fusefs kmod
端口安装fuse内核模块,从devel
部分的py fusefs
端口安装库。par2
命令可在名为par2cmdline
的端口中找到。为了编译文档,你需要pandoc,可以在
textproc
部分中名为hs pandoc
的端口中找到它。
关于NetBSD/pkgsrc
请参阅
pkgsrc/sysutils/bup
,它应该是最新的稳定版本,并包含手册页。它包含合理的依赖项(git
、par2
、py-fuse-bindings
)。fuse-python
包很难找到,它是由sourceforge上的fuse项目分发的python语言绑定的一个单独的tarball。它以pkgsrc/sysutils/bup
的形式提供,在NetBSD 5上,bup-fuse
与之配合使用。bup fuse
将每个目录/文件显示为索引节点0。NetBSD的libc中的目录遍历代码(fts
)会将其解释为一个循环和错误输出,因此ls -R
和find
将不起作用。不支持ACL。如果有人愿意对其进行支持,请调整
dev/compare-trees
。
关于Cygwin
不支持ACL。如果有人愿意对其进行支持,请调整
dev/compare-trees
。在
test/ext/test-misc
中,已禁用两个测试。这些测试检查重复保存是否生成相同的树,以及中间索引是否不会改变SHA1。显然,Cygwin在访问时间方面有一些不寻常的行为(这可能需要进一步调查)。可能相关:http://cygwin.com/ml/cygwin/2007-06/msg00436.html
Notes on OS X
- 不支持ACL。如果有人愿意对其进行支持,请调整
dev/compare-trees
。
工作原理
基本存储:
bup将其数据存储在git格式的存储库中。不幸的是,git本身在bup的用例中并没有表现得很好(大量的文件、大小巨大的文件、保留文件权限/所有权都很重要),所以除了一些帮助程序之外,我们基本上不使用git的代码。例如,bup有自己的git打包文件编写器,它是用python编写的。
基本上,bup split读取stdin上的数据(或从命令行上指定的文件),使用滚动校验和(类似于rsync)将其分解成块,并将这些块保存到新的git packfile
中。每个备份至少有一个git打包文件。
在决定是否将特定块写入新的packfile时,bup首先检查存在的所有其他packfile,看看它们是否已经拥有该块。如果是,则跳过该块。
git包分为两部分:包本身_(.pack)_和索引_(.idx)_。索引非常小,包含包中所有对象的列表。因此,在生成远程备份时,我们不必从远程服务器获得包文件的副本:本地端只需下载服务器索引文件的副本,并将对象与生成新包时的对象进行比较,然后直接发送到服务器。
bup split
和bup save
的-n
选项是要创建的备份的名称,但实际上它是作为git分支实现的。因此,您可以做一些有趣的事情,比如使用git签出一个特定的分支,并接收一组与您拆分的文件相对应的区块文件。
如果使用-b
或-t
或-c
而不是-n
,bup split将分别向标准输出一个blob列表、一个包含该blob列表的树或一个包含该树的提交。您可以使用它来构建自己的脚本,用这些值执行某些操作。
bup索引:
“bup index”遍历文件系统并更新文件(默认情况下,文件名为~/.bup/bupindex
),以包含每个文件和目录的名称、属性以及可选的git SHA1(blob id)。
“bup save”相当于多次运行“bup split”,在索引中每个文件运行一次,然后合成一个包含所有结果对象的git树。除此之外,这使得“git diff”更加有用(与拆分tarball相比,tarball本质上是一个大的二进制blob)。然而,由于bup将大文件分割成更小的块,生成的树结构与git本身存储的_并不完全一致_。此外,“bup save”使用的树格式将来可能会更改,以支持存储文件所有权、更复杂的文件权限等。
如果文件以前是由“bup save”编写的,则其git blob/tree id存储在索引中。这使得“bup save”可以避免读取该文件以生成将来的增量备份,除非有很多文件发生了更改,它可以运行得更快。
这些离谱的玩意我们会修好的
我们非常欢迎您帮助解决这些问题或其他问题。如果你想帮忙,加入邮件列表(见下文)。
“bup save”和“bup restore”对元数据支持还不成熟。
On the plus side, they actually do have support now, but it’s new, and not remotely as well tested as tar/rsync/whatever’s. However, you have to start somewhere, and as of 0.25, we think it’s ready for more general use. Please let us know if you have any trouble.
Also, if any strip or graft-style options are specified to ‘bup save’, then no metadata will be written for the root directory. That’s obviously less than ideal.
bup is overly optimistic about mmap. Right now bup just assumes that it can mmap as large a block as it likes, and that mmap will never fail. Yeah, right… If nothing else, this has failed on 32-bit architectures (and 31-bit is even worse – looking at you, s390).
To fix this, we might just implement a FakeMmap[1] class that uses normal file IO and handles all of the mmap methods[2] that bup actually calls. Then we’d swap in one of those whenever mmap fails.
This would also require implementing some of the methods needed to support “[]“ array access, probably at a minimum getitem, setitem, and setslice [3].
[1] http://comments.gmane.org/gmane.comp.sysutils.backup.bup/613 [2] http://docs.python.org/2/library/mmap.html [3] http://docs.python.org/2/reference/datamodel.html#emulating-container-types
‘bup index’ is slower than it should be.
It’s still rather fast: it can iterate through all the filenames on my 600,000 file filesystem in a few seconds. But it still needs to rewrite the entire index file just to add a single filename, which is pretty nasty; it should just leave the new files in a second “extra index” file or something.
bup could use inotify for really efficient incremental backups.
You could even have your system doing “continuous” backups: whenever a file changes, we immediately send an image of it to the server. We could give the continuous-backup process a really low CPU and I/O priority so you wouldn’t even know it was running.
bup only has experimental support for pruning old backups.
While you should now be able to drop old saves and branches with
bup rm
, and reclaim the space occupied by data that’s no longer needed by other backups withbup gc
, these commands are experimental, and should be handled with great care. See the man pages for more information.Unless you want to help test the new commands, one possible workaround is to just start a new BUP_DIR occasionally, i.e. bup-2013, bup-2014…
bup has never been tested on anything but Linux, FreeBSD, NetBSD, OS X, and Windows+Cygwin.
There’s nothing that makes it inherently non-portable, though, so that’s mostly a matter of someone putting in some effort. (For a “native” Windows port, the most annoying thing is the absence of ssh in a default Windows installation.)
bup needs better documentation.
According to an article about bup in Linux Weekly News (https://lwn.net/Articles/380983/), “it’s a bit short on examples and a user guide would be nice.” Documentation is the sort of thing that will never be great unless someone from outside contributes it (since the developers can never remember which parts are hard to understand).
bup is “relatively speedy” and has “pretty good” compression.
…according to the same LWN article. Clearly neither of those is good enough. We should have awe-inspiring speed and crazy-good compression. Must work on that. Writing more parts in C might help with the speed.
bup has no GUI.
Actually, that’s not stupid, but you might consider it a limitation. See the “Related Projects” list for some possible options.
More Documentation
bup has an extensive set of man pages. Try using ‘bup help’ to get started, or use ‘bup help SUBCOMMAND’ for any bup subcommand (like split, join, index, save, etc.) to get details on that command.
For further technical details, please see ./DESIGN.
How you can help
bup is a work in progress and there are many ways it can still be improved. If you’d like to contribute patches, ideas, or bug reports, please join the bup mailing list:
You can find the mailing list archives here:
1 | http://groups.google.com/group/bup-list |
and you can subscribe by sending a message to:
1 | bup-list+subscribe@googlegroups.com |
You can also reach us via the #bup IRC channel at ircs://irc.libera.chat:6697/bup on the libera.chat network or via this web interface.
Please see ./HACKING for additional information, i.e. how to submit patches (hint - no pull requests), how we handle branches, etc.
Have fun,
Avery