公司业务逐渐扩大时,假如使用的网站或者APP的后端服务器所使用的语言是PHP,若是要想运行PHP代码,须要配置一个lamp或lnmp的环境,最后还须要把代码上传到服务器上去,可是在日常工做中常常有一些新的业务改变,这个时候就须要去修改代码,若是服务器很少还能够快速的在服务器上修改,可是若是有50台或更多服务器,那么就不可能直接在服务器进行修改了,这个时候就可使用到分发系统这样的上线工具进行上线,发布上线代码,所谓的分发系统也就是上线的shell脚本,最核心的东西就是expect,expect也能够说是一种脚本语言,和shell很像,能够用它去实现传输文件,还能够实现自动远程登陆执行命令,不须要输入密码。html
使用什么工具上线代码,所谓上线就是把开发人员写的代码发布到线上环境去。linux
分发系统如何实现发布上线代码,首先要准备一台模板的机器,这台机器上的代码是最新的代码,是须要准备上线的代码,另外要给这50台电脑上线代码,还须要知道50台电脑的IP和对应的用户密码,而后使用expect脚本借助于rsync把这些代码推送到50台机器上,假如说还须要执行一些命令,还可使用expect远程登陆后去执行命令,就是这样的一个过程实现新代码上线发布。shell
一、yum安装expect 软件包后端
[root@localhost ~]# yum install -y expect
二、编写expect脚本
示例1:经过expect脚本自动远程登陆,并执行命令bash
[root@localhost ~]# cat ssh.expect #! /usr/bin/expect #定义主机变量 set host "192.168.66.132" #定义密码变量 set passwd "*****55" #远程登录机器的语句 spawn ssh root@$host #初次登录会有yes和no的提示 expect { "yes/no" { send "yes\r"; exp_continue} "password:" { send "$passwd\r" } } interact
•别忘记给脚本加上执行权限服务器
[root@localhost ~]# chmod a+x ssh.expect
三、执行效果多线程
[root@localhost ~]# ./ssh.expect spawn ssh root@192.168.66.132 Are you sure you want to continue connecting (yes/no)? yes Warning: Permanently added '192.168.66.132' (ECDSA) to the list of known hosts. root@192.168.66.132's password: Last login: Fri Aug 3 15:30:28 2018 from 192.168.66.1 [root@lnmp-server ~]# 已经自动登陆到192.168.66.132 这台机器
示例2:经过expect脚本自动远程登陆,并执行命令最后退出。dom
[root@localhost sbin]# vi touch.expect #!/usr/bin/expect set user "root" set passwd "*****55" spawn ssh $user@192.168.66.132 expect { "yes/no" { send "yes\r"; exp_continue} "password:" { send "$passwd\r" } } expect "]*" send "touch /tmp/test.txt\r" expect "]*" send "echo haha > /tmp/test.txt\r" expect "]*" send "exit\r"
•别忘记给脚本加上执行权限ssh
[root@localhost sbin]# chmod a+x touch.expect
执行效果ide
[root@localhost sbin]# ./touch.expect spawn ssh root@192.168.66.132 #由于不是第一次登录了,因此没有yes or no的提示 root@192.168.66.132's password: Last login: Fri Aug 3 15:50:39 2018 from 192.168.66.131 [root@lnmp-server ~]# touch /tmp/test.txt [root@lnmp-server ~]# echo haha > /tmp/test.txt [root@lnmp-server ~]# [root@localhost sbin]#
查看192.168.66.132/tmp目录是否自动建立了test.txt
[root@lnmp-server ~]# ll /tmp/test.txt -rw-r--r-- 1 root root 5 8月 3 15:50 /tmp/test.txt [root@lnmp-server ~]# cat /tmp/test.txt haha
•比较ssh.expect和touch.expect脚本的区别,ssh.expect脚本仅仅是登陆进去,而后interact表示expect脚本结束了,可是会停留在机器上不会退出登陆的机器,touch.expect脚本登陆完以后,还须要执行几条命令,最后才是退出结束脚本
[root@localhost ~]# cat ssh.expect #! /usr/bin/expect #定义主机变量 set host "192.168.66.132" #定义密码变量 set passwd "*****55" #远程登录机器的语句 spawn ssh root@$host #初次登录会有yes和no的提示 expect { "yes/no" { send "yes\r"; exp_continue} "password:" { send "$passwd\r" } } interact [root@localhost sbin]# cat touch.expect #!/usr/bin/expect set user "root" set passwd "*****55" spawn ssh $user@192.168.66.132 expect { "yes/no" { send "yes\r"; exp_continue} "password:" { send "$passwd\r" } } expect "]*" send "touch /tmp/test.txt\r" expect "]*" send "echo haha > /tmp/test.txt\r" expect "]*" send "exit\r"
shell脚本能够传递参数,expect也是能够传递参数的,不一样的是expect的参数是从0开始的
示例3:expect脚本传递参数
[root@jimmylinux-001 sbin]# vi 3.expect #!/usr/bin/expect set user [lindex $argv 0] set host [lindex $argv 1] set passwd "*****55" set cm [lindex $argv 2] spawn ssh $user@$host expect { "yes/no" { send "yes\r"} "password:" { send "$passwd\r" } } expect "]*" send "$cm\r" expect "]*" send "exit\r"
•别忘记给脚本加上执行权限
[root@localhost sbin]# chmod +x 3.expect
执行脚本测试
###传递多条命令,须要使用双引号引发来,中间用分号分隔。 [root@localhost sbin]# ./3.expect root 192.168.66.132 "ls;w;vmstat 1 3" spawn ssh root@192.168.66.132 root@192.168.66.132's password: Last login: Fri Aug 3 15:51:37 2018 from 192.168.66.131 [root@lnmp-server ~]# ls;w;vmstat 1 3 1.txt 2.sh 3.sh anaconda-ks.cfg 16:05:41 up 38 min, 2 users, load average: 0.00, 0.01, 0.05 USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT root pts/0 192.168.66.1 15:30 14:37 0.00s 0.00s -bash root pts/1 192.168.66.131 16:05 0.00s 0.00s 0.00s w procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- r b swpd free buff cache si so bi bo in cs us sy id wa st 2 0 0 272780 2076 155580 0 0 55 5 75 95 0 0 98 1 0 0 0 0 272780 2076 155600 0 0 0 0 59 60 0 1 99 0 0 0 0 0 272780 2076 155600 0 0 0 0 55 53 0 0 100 0 0
使用expect脚本实如今一台机器上把文件同步到另一台机器上,这里须要用到核心命令rsync,若是是手动方式进行同步,那么还须要单独输入密码,因此没有脚本方式操做方便
•注意,由于用到了rsync命令,因此两边机器都要安装rsync
yum install -y rsync
示例4:自动同步文件
[root@localhost sbin]# vi 4.expect #!/usr/bin/expect set passwd "*****55" spawn rsync -av root@192.168.66.132:/tmp/test.txt /tmp/ expect { "yes/no" { send "yes\r"} "password:" { send "$passwd\r" } } expect eof #若是不加这条语句,那么尚未开始执行数据传输,就立刻结束了,甚至有可能尚未远程登陆成功,就已经退出来了,因此脚本里面必需要加这条语句。
给脚本加执行权限,并执行脚本测试
[root@localhost sbin]# chmod +x 4.expect [root@localhost sbin]# ./4.expect spawn rsync -av root@192.168.66.132:/tmp/test.txt /tmp/ root@192.168.66.132's password: receiving incremental file list test.txt sent 43 bytes received 98 bytes 282.00 bytes/sec total size is 5 speedup is 0.04 [root@localhost sbin]# ll /tmp/test.txt -rw-r--r-- 1 root root 5 8月 3 15:51 /tmp/test.txt
以前的3.expect文件默认是10秒钟超时,固然也是能够增长超时时间甚至可让永久不超时。
只须要在脚本文件中添加设置timeout的变量便可
set timeout 3 设置超时秒数,若是是-1表示永久不会超时
示例5:指定host和要同步的文件,这种方式只适合同步一个文件。
[root@localhost sbin]# vi 5.expect #!/usr/bin/expect set passwd "*****55" set host [lindex $argv 0] set file [lindex $argv 1] spawn rsync -av $file root@$host:$file expect { "yes/no" { send "yes\r"} "password:" { send "$passwd\r" } } expect eof
给脚本加执行权限,并执行脚本测试
[root@localhost sbin]# chmod +x 5.expect [root@localhost sbin]# ./5.expect 192.168.66.132 ./5.expect spawn rsync -av ./5.expect root@192.168.66.132:./5.expect root@192.168.66.132's password: sending incremental file list 5.expect sent 310 bytes received 35 bytes 690.00 bytes/sec total size is 217 speedup is 0.63 切换到加外一台机查看 [root@lnmp-server ~]# ll -rwxr-xr-x 1 root root 217 8月 3 16:27 5.expect
需求背景:对于大公司而言,确定时不时会有网站或者配置文件更新,并且使用的机器确定也是好多台,少则几台,多则几十甚至上百台。因此,自动同步文件是相当重要的。
实现思路:首先要有一台模板机器,把要分发的文件准备好,而后只要使用expect脚本批量把须要同步的文件分发到目标机器便可。
•核心命令:rsync -av --files-from=list.txt / root@host:/
文件分发系统的实现
一、编写 rsync.expect
[root@localhost sbin]# vi rsync.expect #!/usr/bin/expect set passwd "*****55" set host [lindex $argv 0] set file [lindex $argv 1] spawn rsync -avR --files-from=$file / root@$host:/ ##若是不肯定对方机器有相同的路径,能够加-avR expect { "yes/no" { send "yes\r"} "password:" { send "$passwd\r" } } expect eof
•别忘记加上执行权限chmod +x rsync.expect
二、编写文件列表 file.list
[root@localhost sbin]# vi /tmp/file.list /tmp/test1.txt /tmp/test2.txt /tmp/test3.txt
三、编写IP地址列表文件 ip.list
[root@localhost sbin]# vi /tmp/ip.list 192.168.66.129 192.168.66.132
四、建立 rsync.sh 循环调用rsync.expect去执行命令
[root@localhost sbin]# vi rsync.sh #!/bin/bash for ip in `cat /tmp/ip.list` do ./rsync.expect $ip /tmp/file.list done
五、测试效果
[root@localhost sbin]# sh rsync.sh spawn rsync -avR --files-from=/tmp/file.list / root@192.168.66.129:/ root@192.168.66.129's password: building file list ... done tmp/ tmp/test1.txt tmp/test2.txt tmp/test3.txt sent 168 bytes received 56 bytes 89.60 bytes/sec total size is 0 speedup is 0.00 spawn rsync -avR --files-from=/tmp/file.list / root@192.168.66.132:/ root@192.168.66.132's password: building file list ... done tmp/ tmp/test1.txt tmp/test2.txt tmp/test3.txt sent 187 bytes received 57 bytes 162.67 bytes/sec total size is 0 speedup is 0.00 ##切换到机器上查看 [root@lnmp-server ~]# ls /tmp/ test1.txt test2.txt test3.txt
想批量远程执行命令,能够经过2个脚原本实现
一、建立 exe.expect 脚本
[root@localhost sbin]# vi exe.expect #!/usr/bin/expect set host [lindex $argv 0] set passwd "*****55" set cm [lindex $argv 1] spawn ssh root@$host expect { "yes/no" { send "yes\r"} "password:" { send "$passwd\r" } } expect "]*" send "$cm\r" expect "]*" send "exit\r"
二、添加执行权限
[root@localhost sbin]# chmod +x exe.expect
三、建立 exe.sh 脚本循环执行
[root@localhost sbin]# cat exe.sh #!/bin/bash for ip in `cat /tmp/ip.list` do ./exe.expect $ip "hostname" done
注意:/tmp/ip.list要自已建立
四、测试脚本
[root@lnmp-server ~]# [root@localhost sbin]# sh exe.sh spawn ssh root@192.168.66.129 root@192.168.66.129's password: Last login: Wed Aug 1 20:16:03 2018 from 192.168.66.131 [root@localhost ~]# hostname localhost.localdomain [root@localhost ~]# spawn ssh root@192.168.66.132 root@192.168.66.132's password: Last login: Fri Aug 3 16:57:29 2018 from 192.168.66.131 [root@lnmp-server ~]# hostname lnmp-server
扩展:
shell多线程 http://blog.lishiming.net/?p=448
给你提供一本电子书 连接:http://pan.baidu.com/s/1mg49Taw 密码:yk4b
shell习题作一下 http://www.apelearn.com/study_v2/chapter15.html#shll