课题要求:
有两台以LINUX为环境的服务器都安装了CVS,一台是常用的称为 服务器A , 另一台是备份用的称为 服务器B。
现在要求每天将服务器A上的CVS内容自动备份到服务器B的CVS上去,并且每个月产生一个版本。一旦服务器A 发生故障,可以立即使用服务器B上的CVS。
方案前期准备:
1,服务器A 服务器B 上已经安装了 两个一模一样的CVS, 包括希望备份的项目,可以访问的用户名密码等。
2,两台服务器之间的网络访问正常。
3,已经安装了expect
解决方案:
1,CVS有 Export 命令, 可以利用这个命令将希望备份的项目导出
2,CVS也有Import命令, 可以利用这个命令将导出的文件导入到用于备份的服务器中。
3,利用Linux的crontab 自动来执行上述两项任务。
4,由于要求每天都要备份且每个月又要自动产生一个版本,所以可以将每天执行的备份写成一个shell脚本,每月执行的备份写成另一个shell脚本, 然后用crontab 来控制这两个脚本。
实施过程:
1,先撰写每天执行的备份脚本 cvsbkday.sh 内容如下:
1 #!/bin/bash
2 logfilename=/home/cvsroot/cvsbk/logs/$(date +%Y-%m-%d_%H:%M:%S.txt)
3 vendortag=vendortag_current
4 releasetag=releasetag_current
5 echo $logfilename > $logfilename
6 echo $vendortag >> $logfilename
7 echo $releasetag >> $logfilename
8 /home/cvsroot/bin/autologincvs.sh
9 cd /home/cvsroot/cvsbk/
10 rm -rf stastt
11 echo "===== Export stastt Start! =====" >>$logfilename
12 /usr/bin/cvs -d:pserver:qian@localhost:/home/cvsroot/stastt export -D now stastt>>$logfilename
13 echo "===== Export stastt End! =====">>$logfilename
14 cd /home/cvsroot/cvsbk/stastt/
15 echo "===== Import stastt to serverB Start! =====">>$logfilename
16 /usr/bin/cvs -d:pserver:qian@serverB:/home/cvsroot/stastt import -m'import stastt' stastt $vendortag $releasetag >>$logfilename
17 echo "===== Import stastt to serverB End! =====">>$logfilename
解释:
第2行: 执行备份时的日志文件的文件位置及名称,其中用到了命令替换,$(date +%Y-%m-%d_%H:%M:%S.txt) 根据当前的时间产生一个时间格式的文件名。
$(subcommand) 让用户在子shell 中运行任意的命令,并把结果合并在命令行中。
date(1) man page 可以查看 时间格式字符串的设计用法
第5行: 将文件名写入日志文件中
第8行: 先执行登录CVS服务器,用到了另一个shell 脚本autologincvs.sh,内容如下:
#!/usr/expect/bin/expect
# Auto login in CVS by user qian
set user "qian"
set passwd "qian"
spawn cvs -d:pserver:qian@localhost:/home/cvsroot/stastt login
expect "*password:"
send "$passwd/n"
expect eof
spawn cvs -d:pserver:qian@serverB:/home/cvsroot/stastt login
expect "*password:"
send "$passwd/n"
expect eof
exit
CVS的登录命令是 cvs -d:pserver:用户名@主机名:/home/cvsroot/stastt login
但是这是一个交互命令,之后会要求用户输入密码,所以为了实现自动登录必须用到expect, 对于不太了解Except的朋友可以去网上搜索一下“Except TCL 安装”和 “expect的基本用法”学习一下相关知识。
autologincvs.sh 文件中用到两次登录 主机,一次是本地,一次是用于备份的服务器 ServerB, 这样就可以实现import 了否则执行导入时系统会出错。
第9行: 切换到备份的目录
第10行: 清空导出目录以便马上导出新的内容
第12行: 导出命令,将导出代码放到stastt目录下,并将结果写到日志文件中
/usr/bin/cvs -d:pserver:qian@localhost:/home/cvsroot/stastt export -D now stastt>>$logfilename
第14行: 切换至导出文件夹
第16行: 将导出文件夹中的内容 导入到 备份服务器中去,并将结果写入日志
/usr/bin/cvs -d:pserver:qian@serverB:/home/cvsroot/stastt import -m'import stastt' stastt $vendortag $releasetag >>$logfilename
由于设定了 $vendortag $releasetag 所以 vendortag=vendortag_current , releasetag=releasetag_current 的就是当前版本。
至此,每日的备份工作已经完成
2,再撰写每月执行的备份脚本 cvsbkmonth.sh 内容如下:
#!/bin/bash
logfilename=/home/cvsroot/cvsbk/logs/$(date +%Y-%m-%d_%H:%M:%S.txt)
vendortag=vendortag_$(date +%Y-%m-%d)
releasetag=releasetag_$(date +%Y-%m-%d)
echo $logfilename > $logfilename
echo $vendortag >> $logfilename
echo $releasetag >> $logfilename
cd /home/cvsroot/cvsbk/
rm -rf stastt
echo "===== Export stastt Start! =====" >>$logfilename
/usr/bin/cvs -d:pserver:qian@localhost:/home/cvsroot/stastt export -D now stastt>>$logfilename
echo "===== Export stastt End! =====">>$logfilename
cd /home/cvsroot/cvsbk/stastt/
echo "===== Import stastt to vmlinux Start! =====">>$logfilename
/usr/bin/cvs -d:pserver:qian@vmlinux:/home/cvsroot/stastt import -m'import stastt' stastt $vendortag $releasetag >>$logfilename
echo "===== Import stastt to vmlinux End! =====">>$logfilename
这个脚本的内容的内容和 cvsday.sh 基本相同,不再详细解释,唯一的差别在于
vendortag=vendortag_$(date +%Y-%m-%d)
releasetag=releasetag_$(date +%Y-%m-%d)
这是为了表明不同的每月版本而采用了时间格式来加以区别。
3, 设定crontab 文件,内容如下:
1 1 * * * /home/cvsroot/bin/cvsbkday.sh
30 1 1 * * /home/cvsroot/bin/cvsbkmonth.sh
第一行: 每天1点1分执行 脚本 /home/cvsroot/bin/cvsbkday.sh
第二行: 每月1号1点30分 执行脚本 /home/cvsroot/bin/cvsbkmonth.sh
cron命令行包括6个用空白符分割的字段,从左至右依次为:
1, minute
2, hour
3, day of month
4, month( 1 = January, 2=February, ...)
5, day of week (0=Sunday, 1=Monday, ...)
6, command to run
后记
以上所述,均为本人个人经验,已经过实验证明可行,在实际使用中较正常,至今没有什么大问题,各位可视情况参考使用。
其中涉及到linux , shell 编程, cvs , expect 等诸多技术,代码虽然不长,但是还是需要技术者有一定的基础。
各位读者如有其它更好办法,还望探讨告知,此文全当抛砖引玉了,以待佳作降临。