摘要: 
备份是系统管理中最艰巨、最容易被忽略的工作之一,同时也是最重要的工作之一。备份是防御硬件故障、非法入侵和系统安全的最大威胁——终端用户的最后一道防线。有许多备份系统价值数千美元,它们使用到处都是 Bug 的专有版权软件将数据存入昂贵的磁带机中,而实际上有更好的方法:Rsync 和廉价的磁盘阵列。 
_________________ _________________ _________________ 
问题 
我可以给出一个长长的列表说明备份是系统管理员的梦魇。不过如果你是系统管理员的话,我可能就不用列了。这些原因包括:运行中常常出故障的昂贵硬件,难于管理的昂贵软件,恢复多版本的文件所耗费的大量时间。更糟的是,不到万不得已必须做备份的时候,备份工作通常只有很低的优先级。如果你做了备份/ 恢复,还有可能会发生下面的对话: 
用户: "我丢了一个文件,我需要你立刻把它找回来。" 
系统管理员: "Ok, 文件名是什么?" 
用户: "我不记得了, 我只记得文件名中有一个字母是'e'。" 
系统管理员: "Ok, 那么他在哪个目录中?" 
用户: "我不知道, 它可能在这些目录树中的一个。" 
系统管理员: "哦... 那你是否记得你上次使用这个文件的日期?" 
用户: "嗯....我想应该是二月或是四月的一个星期四。有什么问题吗? 我想你应该已经备份了系统用于应付这样的事情吧。" 
替代品 Rsync 
Rsync 是一个小巧的算法的强大实现。它最基本的功能是高效地镜像一个文件系统的能力。使用 rsync,可以灵活地选用一组网络协议,诸如 nfs、smb 或 ssh,方便地让一个文件系统与另一个文件系统保持同步更新。Rsync 的第二个功能,也就是备份系统使用的功能,它可以把已经发生改变或是被删除的文件的老的版本归档。Rsync 的功能太多了,不可能在这里一一叙述,笔者强烈建议读者阅读 rsync.samba.org 上的资料来研读 rsync。 
备份系统 
简单地说,这个备份系统使用了廉价的 Linux 主机,并使用了廉价的磁盘和一个称为 rsync 的短小的 shell 脚本。[图 1] 当进行备份的时候,我们告诉 rsync 建立一个称为 'YY-MM-DD' 的目录,作为存储变化增量的地方。之后,rsync 检查要备份的服务器上的变化。如果一个文件发生了变化,就把老的版本复制到增量目录,并覆盖主备份目录中的文件。[图 2] 
RSYNC 备份过程 
http://blog.taqu.com/uploadfiles/200510229947.png

通常一天的变化量往往只占整个文件系统的一个很小的百分比。笔者发现这个典型值平均在 0.5% 到 1%。这样,使用一组两倍于服务器文件系统的尺寸的磁盘,我们可以在硬盘上保存 50-100 天的增量备份。当磁盘满了,只要换一组新的磁盘替换老的就可以了。在实际操作中,磁盘上可能可以保存超过半年的增量备份数据。事实上,如果你能找到一些存储空间,可以在更换磁盘之前把增量备份复制过去。使用这种方法,你可以在磁盘上保存任意数量的增量备份。 
增量文件是如何处理的 
优势:简化了灾难恢复和文件还原 
回到开头的那个设想的对话。现在换掉笨重的基于磁带的备份系统,设想一下有六个月的增量备份正在你的 Linux 主机中愉快地等着你呢。使用你喜欢的 locate/find/grep 的组合,你可以找出所有的我们设想出来的那个用户的可能发生问题的文件,它的文件名中包含 'e',时间戳是二月或四月的一个星期四,将它们放到他的 home 目录下的一个目录中。接下来,找出那个版本的文件是用户需要的那个文件的问题就成为了我们最喜欢的一类问题——别人的问题。 
下面设想一个我们喜欢的场景-- 完全的故障。比如你有一个大的 nfs/samba 服务器出了故障,好了,如果你已经备份了你的 samba 配置,你可以启动你的备份服务器作为故障服务器的一个几分钟之内的只读的替代服务器。你试试看可不可以用磁带做到这一点。 
Rsync/硬盘备份系统和磁带备份系统的比较 
磁带备份 Rsync 
成本 非常高 低 
完全备份 快 快 
增量备份 快 快 
完全恢复 非常慢,可能位于多个磁带上 快 -- 全在磁盘上 
文件恢复 慢,可能位于多个磁带上,难以查找正确的版本 非常快 - 全都位于磁盘上,而且你可以使用 UN*X 的诸如 find, locate, grep 等查找工具的强大功能 
完全故障 唯一的选择是完全恢复 在关键时刻备份服务器可以作为紧急的文件服务器 
用到的工具 
有很多方法来建立这个系统。所有的工具都是开源的,包括在一个标准的 Linux 发布版之中,而且非常灵活。这里我们描述一个可能配置,但这决不是唯一的方法。 
* 服务器: 笔者使用 RedHat Linux。任何发布版,任何 UN*X 都应该可以。(我甚至在 Mac OS X 上面配置过)一点忠告:更多的内存会有好处的。 
* 磁盘: 我们发现最简单的构建一组廉价的磁盘的方法是使用一个 PCI 火线卡,连接一组廉价的放在外置火线硬盘盒中的 IDE 硬盘。设置 Linux 去像一个大的 RAID 分区一样用这些硬盘相当容易。 
* 软件: Rsync 是一个伟大的工具。Rsync 常常用于文件系统的镜像。如果你不知道 rsync,请看看 rsync.samba.org。 
* 连接到文件服务器: Rsync 非常灵活,我们使用 nfs 和 smbfs。你也可以通过在文件服务器上运行一个rsync 守护进程,使用 rsync 自己的网络协议。你也可以让 rsync 使用 ssh 来安全地被分远端网站。可以参考下面列出的资源来设置这些连接方式。 
编写为脚本 
这个脚本的基本形式来自于 rsync 的网站。其实只有一条命令: 
rsync --force --ignore-errors --delete --delete-excluded --exclude-from=exclude_file --backup --backup-dir=`date +%Y-%m-%d` -av 
关键的参数是: 
* --backup: 在覆盖前备份文件 
* --backup-dir=`date +%Y-%m-%d`: 为备份的文件建立一个备份目录,看上去就像: 2002-08-15 
* -av: 存档(archive)模式和详细输出(verbose)模式。 
下面的脚本通过 Linux 内建的 cron 功能,可以每天晚上自动运行。比如要让程序每天晚上 11 点运行,使用"crontab -e"命令,然后输入: 
0 23 * * * /path/to/your/script 
脚本t 
这里是我的 shell 完整的脚本。再说一次,有很多不同的方法可以做到这些,这只是其中的一个实现版本。 
#!/bin/sh 
######################################################### 
# Script to do incremental rsync backups 
# Adapted from script found on the rsync.samba.org 
# Brian Hone 3/24/2002 
# This script is freely distributed under the GPL 
######################################################### 
################################## 
# Configure These Options 
################################## 
################################### 
# mail address for status updates 
# - This is used to email you a status report 
################################### 
MAILADDR=your_mail_address_here 
################################### 
# HOSTNAME 
# - This is also used for reporting 
################################### 
HOSTNAME=your_hostname_here 
################################### 
# directory to backup 
# - This is the path to the directory you want to archive 
################################### 
BACKUPDIR=directory_you_want_to_backup 
################################### 
# excludes file - contains one wildcard pattern per line of files to exclude 
# - This is a rsync exclude file. See the rsync man page and/or the 
# example_exclude_file 
################################### 
EXCLUDES=example_exclude_file 
################################### 
# root directory to for backup stuff 
################################### 
ARCHIVEROOT=directory_to_backup_to 
######################################### 
# From here on out, you probably don't # 
# want to change anything unless you # 
# know what you're doing. # 
######################################### 
# directory which holds our current datastore 
CURRENT=main 
# directory which we save incremental changes to 
INCREMENTDIR=`date +%Y-%m-%d` 
# options to pass to rsync 
OPTIONS="--force --ignore-errors --delete --delete-excluded \ 
--exclude-from=$EXCLUDES --backup --backup-dir=$ARCHIVEROOT/$INCREMENTDIR -av" 
export PATH=$PATH:/bin:/usr/bin:/usr/local/bin 
# make sure our backup tree exists 
install -d $ARCHIVEROOT/$CURRENT 
# our actual rsyncing function 
do_rsync() 

rsync $OPTIONS $BACKUPDIR $ARCHIVEROOT/$CURRENT 

# our post rsync accounting function 
do_accounting() 

echo "Backup Accounting for Day $INCREMENTDIR on $HOSTNAME:">/tmp/rsync_script_tmpfile 
echo >> /tmp/rsync_script_tmpfile 
echo "################################################">>/tmp/rsync_script_tmpfile 
du -s $ARCHIVEROOT/* >> /tmp/rsync_script_tmpfile 
echo "Mail $MAILADDR -s $HOSTNAME Backup Report < /tmp/rsync_script_tmpfile" 
Mail $MAILADDR -s $HOSTNAME Backup Report < /tmp/rsync_script_tmpfile 
echo "rm /tmp/rsync_script_tmpfile" 
rm /tmp/rsync_script_tmpfile 

# some error handling and/or run our backup and accounting 
if [ -f $EXCLUDES ]; then 
if [ -d $BACKUPDIR ]; then 
# now the actual transfer 
do_rsync && do_accounting 
else 
echo "cant find $BACKUPDIR"; exit 
fi 
else 
echo "cant find $EXCLUDES"; exit 
fi