在案例十六中已经介绍过expect脚本的使用,能够远程登陆机器并执行命令,其实expect脚本也能够传输文件。本案例的需求就是经过expect脚原本同步文件,从而实现代码上线。生产环境中一个业务一般跑在多台服务器上,也就是负载均衡,因此这些机器上运行的代码必需要保持一致。怎么实现一致?有两种方案。web
一、经过共享的方式shell
若是机器量很少,可使用NFS实现,若是要求稳定性最好是使用专业的存储设备(NAS、SAN等),这种方式架构以下:bash
这种架构的优势是方便维护,好比有代码更新时,只须要更新一台机器上的代码,则其余机器上都会跟着更新。缺点是,机器量大的话,共享存储会成为瓶颈,甚至因为对文件的争抢形成性能问题。还有一点,共享存储这里是一个很大的单点隐患,不出故障一切都OK,一旦出故障,则整个业务都挂掉,影响很是大。服务器
二、分布式架构
既然经过共享的方式有很多缺点,那么就选择另一种方式,即把代码存到每一台web服务器的本地磁盘上,如图所示:负载均衡
这样作的好处是,没有存储性能问题,没有资源争抢冲突,也没有单点故障的隐患。缺点是,每次代码更新须要对全部web服务器就行更新,比较繁琐。虽然步骤繁琐,但大多数企业都会选择该方式。本案例的背景就是第二种方式,具体要求以下:ssh
1)提供一个全部web服务器的IP列表ip.list。分布式
2)假设全部web服务器上有一个普通用户user01,密码为SGs2ox6uj,该用户为同步代码的用户。ide
3)每次代码上线会提供一个文件列表file.list(即要更改的文件列表)。工具
知识点一:rsync同步文件经过文件列表
rsync这个同步文件的工具虽然在前面案例出现过,但经过一个文件列表来同步文件并不常见,先看示例:
# cat 1.txt /tmp/123/1.sh /root/test/a.txt /etc/passwd # rsync -av --files-from=./1.txt / root@192.168.93.130:/
说明:1.txt为一个文件列表,即要同步的文件列表;rsync的--files-from选项指定要同步文件的列表文件(1.txt的路径,能够是绝对路径,也能够是相对路径),这个文件列表内容其实就是一堆文件路径,这个路径建议用绝对路径,否则会出错;若是文件列表中的文件路径为绝对路径,则rsync的源目录必须为/,目标目录也必须为/。
知识点二:expect脚本同步文件
跟远程执行命令相似,expect脚本要想同步文件,spawn后面的shell命令再也不是ssh,而是rsync,示例:
#!/usr/bin/expect set passwd "SGs2ox6uj" set host "192.168.93.130" spawn rsync -a user01@$host:/tmp/test.txt /tmp/ expect { "yes/no" {send "yes\r"} "password:" {send "$passwd\r"} } expect eof 也能够传递参数给expect脚本,示例: #!/usr/bin/expect set passwd "SGs2ox6uj" set host [lindex $argv 0] set file [lindex $argv 1] spawn rsync -a --files-from=$file / user01@$host:/ expect { "yes/no" {send "yes\r"} "password:" {send "$passwd\r"} } expect eof
本案例参考脚本
#/bin/bash ##代码上线 ##做者: ##日期: #提醒用户,是否更新了要上线的代码列表文件 read -p "你是否已经更新了文件列表./file.list?确认请输入y或者Y,不然按其余任意键退出脚本。" c #若是直接按回车,也会退出脚本 if [ -z "$c" ] then exit 1 fi if [ $c == "y" -o $c == "Y" ] then echo "脚本将在2秒后,继续执行。" #每秒输出一个.共输出两个. for i in 1 2 do echo -n "." sleep 1 done echo else exit 1 fi #判断有无./rsync.exp文件 [ -f ./rsync.exp ] && rm -f ./rsync.exp #定义rsync.exp cat >./rsync.exp <
说明:要想在生产环境中使用该脚本,须要先提早建立一个user01用户,而且保证user01用户对web服务器上代码所在目录有写权限。