一、自动登录expect脚本

文件分发系统参考文档地址   http://www.apelearn.com/bbs/thread-8113-1-1.html

分发系统

背景大多数企业都会有这样的需求,业务稍微大一点,它都会去做一些负载均衡,也意味着你的机器有多台,至少得两台,两台的话,你的程序是分别放在了两台机器上或者是多台机器上;假如说要添加一个新的功能,或者说你的程序有一个小bug,那这个时候你如果想这个bug修复,或者说新增一个功能的话,你要去改程序,那很多企业有svn,它是一个代码管理仓库,那我们如果把程序修改了之后呢,先传一份到svn库里边去;如果再智能自动化一点,我可以从咱们服务器上或者测试机上把svn库里的代码直接拽过来,发布到咱们的测试机上,然后再从测试机上呢,测试完成之后没问题了,我再把这些代码呢再拉到咱们线上的服务器上。当然,有的公司没有那么复杂,它可能直接从svn库里面把代码直接拉到咱们线上的服务器上,但是,你拉的时候呢,实际上只拉了一台机器,假如说你负载均衡有三台,那你这三台其中一台更新了,另外两台还没有更新,那怎么办呢?那这个时候你得想办法把代码从这台更新的机器上分发到另外两台机器上去,那分发的话,可以手动去拷贝,用rsycn;当然,也可以从svn里边直接拉过去,这个操作的话可能会复杂一点,一两台机器无所谓,但你机器多了的话,你每台机器都得去操作一下,不好,效率比较低,所以我们想了一种办法:就是在你这一台测试机上或者是这一台生产机器上,你去搞一个脚本,那这个脚本的目的呢,就是把这些新的代码或者说所有的代码同时给它同步到另外的机器上去,一键同步,那咱们这个脚本的目的呢就是为了同步;另外可能还有一种,我同步完成之后呢,我还要去在那台机器上去执行一条命令,那比如我涉及到一个服务,我脚本或者说咱们这个apache、ngix配置文件我更新了,我更新了一台测试没问题了,那另外其他几台,我也要更新一下,那这个时候我更新的时候,我也是通过咱们这个脚本分发,直接分发给其他的机器,因为它们的脚本的配置都是一模一样的,那你分发完成之后呢,是不是就意味着你的服务要重启或者重新reload,怎么办?我就需要去在远程的机器上去执行一些命令,那这个时候,我也需要同时去执行,批量执行,一台一台的登录太麻烦了,很浪费时间,那我也可能通过这个脚本去实现,那今天要讲的就是怎样去实现程序或者配置文件的同步以及命令的远程执行,那么在这涉及到一个概念,叫做expect

使用之前:

[root@wy ~]# rpm -aq | grep expect

[root@wy ~]# yum install -y expect

1、自动远程登录不退出的脚本

[root@wy ~]# mkdir shell

[root@wy ~]# cd shell

[root@wy shell]# vim 1.expect

#!/usr/bin/expect

set host "192.168.219.128"

set passwd "123456"

spawn ssh root@$host

expect {

"yes/no" { send "yes\r"; exp_continue }

"assword:" { send "$passwd\r" }

}

interact

解释说明:

     第一行:设置了一个变量host是谁,类似于shell的定义变量,shell中是host等于什么什么,而expect是这样(如上脚本中)定义变量的,

              host是另一台机器的ip

     第二行:设置密码

     第三行:spawn是expect的一个语句,spawn后面呢就是要登录机器的命令,这条命令其实是shell的命令

     第四行:expect语句模块

             yes/no 第一次登录的话会问;如果不是第一次,它就不会问,后面的语句也就不执行;    \r是回车的意思

             assword 让你输入密码,我们可以简写,可以写你这条命令或者问答问你的最后几个字符;后面的语句让我们输入密码 $passwd

     最后 :interact 结束

注:这个是固定语法

## 执行脚本

[root@wy shell]# chmod +x 1.expect

[root@wy shell]# ./1.expect

spawn ssh root@192.168.219.128

The authenticity of host '192.168.219.128 (192.168.219.128)' can't be established.

RSA key fingerprint is e9:da:13:28:7e:90:b0:e9:5e:df:e0:f9:e3:09:4c:23.

Are you sure you want to continue connecting (yes/no)? yes

Warning: Permanently added '192.168.219.128' (RSA) to the list of known hosts.

root@192.168.219.128's password:

Last login: Sat Dec  3 17:11:52 2016 from 192.168.219.1

[root@y2 ~]#

解释说明:

现在的hostname变成了y2;脚本当中交互的passwd少了一个p,是故意的,也就是告诉expect跟用户交互的这个东西,它只是截取了最后面的几个字符而已,匹配时需要输入的东西。

注:这种文件一定要保密,因为涉及到了密码。

## 退出

[root@y2 ~]# logout

Connection to 192.168.219.128 closed.


二、自动登陆后执行命令

2、自动远程登录,执行命令后退出脚本

[root@wy shell]# vim 2.expect

#!/usr/bin/expect

set user "root"

set passwd "123456"

spawn ssh $user@192.168.219.128

expect {

"yes/no" { send "yes\r"; exp_continue }

"assword:" { send "$passwd\r" }

}

expect "]*"

send "touch /tmp/12.txt\r"

expect "]*"

send "echo 1212 > /tmp/12.txt\r"

expect "]*"

send "exit\r

解释说明:

     这个脚本呢是到远程机器上输入一条命令;那输入命令的话,我肯定会看到是root吗,

         如果是root的话,那你会发现( [root@client ~]# ),标示×××部分,是最后一个符号。

     expect "]*"     *表示你有可能是#也有可能是$,因为有的系统它即使是root,也不见得是#,但是它不会是别的了。

                     基本上就是两个,或者可能有其他自定义的,那我们用*就全部都包括了

## 执行脚本

[root@wy shell]# chmod +x 2.expect

[root@wy shell]# ./2.expect  

spawn ssh root@192.168.219.128

root@192.168.219.128's password:

Last login: Mon Dec  5 21:38:00 2016 from master

[root@y2 ~]# touch /tmp/12.txt

[root@y2 ~]# echo 1212 > /tmp/12.txt

[root@y2 ~]# [root@wy shell]#

## 查看一下远程的机器是否有这个文件

[root@y2 ~]# cat /tmp/12.txt

1212


三、expect脚本传递参数

3、传递参数的脚本

[root@wy shell]# vim 3.expect

#!/usr/bin/expect

set user [lindex $argv 0]

set host [lindex $argv 1]

set passwd "123456"

set cm [lindex $argv 2]

spawn ssh $user@$host

expect {

"yes/no" { send "yes\r"; exp_continue }

"assword:" { send "$passwd\r" }

}

expect "]*"

send "$cm\r"

expect "]*"

send "exit\r"

解释说明:

     它跟shell传递参数不一样,shell是$0,$1...,而这是 $argv 0,...  

     cm 是远程要执行的一个命令  

## 执行脚本

[root@wy shell]# chmod +x 3.expect

[root@wy shell]# ./3.expect root 192.168.219.128 "ls /tmp/12.txt"

spawn ssh root@192.168.219.128

root@192.168.219.128's password:

Last login: Mon Dec  5 21:41:06 2016 from 192.168.219.1

[root@y2 ~]# ls /tmp/12.txt

/tmp/12.txt

[root@y2 ~]#  [root@wy shell]#


四、自动同步文件脚本

4、自动同步文件脚本

[root@wy shell]# vim 4.expect

#!/usr/bin/expect

set passwd "123456"

spawn rsync -avzP root@192.168.219.128:/tmp/12.txt /tmp

expect {

"yes/no" { send "yes\r"; exp_continue }

"assword:" { send "$passwd\r" }

}

expect eof

解释说明:

     拷贝文件用rsync

     expect eof  结束,若不写eof,也就意味着你这个东西登录了这台机器,我没有结束,你要给它来一个结束符

注:两边都需要安装rsync(yum install -y rsync)

## 执行脚本

[root@wy shell]# chmod +x 4.expect

[root@wy shell]# ./4.expect

spawn rsync -avzP root@192.168.219.128:/tmp/12.txt /tmp

root@192.168.219.128's password:

receiving incremental file list

12.txt

          5 100%    4.88kB/s    0:00:00 (xfer#1, to-check=0/1)

sent 30 bytes  received 81 bytes  74.00 bytes/sec

total size is 5  speedup is 0.05

## 查看结果

[root@wy shell]# cat /tmp/12.txt

1212

## 测试(修改一下远程机器上文件的内容)

[root@y2 ~]# vim /tmp/12.txt

1212

afslsfsf

[root@wy shell]# ./4.expect      

spawn rsync -avzP root@192.168.219.128:/tmp/12.txt /tmp

root@192.168.219.128's password:

receiving incremental file list

12.txt

         14 100%   13.67kB/s    0:00:00 (xfer#1, to-check=0/1)

sent 36 bytes  received 90 bytes  252.00 bytes/sec

total size is 14  speedup is 0.11

You have new mail in /var/spool/mail/root

[root@wy shell]# cat /tmp/12.txt

1212

afslsfsf

两者区别: expect eof 会退出远程的机器, interact 不会退出那机器。


五、指定ip和指定文件同步脚本

5、指定host和要同步的文件

[root@wy shell]# vim 5.expect

#!/usr/bin/expect

set passwd "123456"

set host [lindex $argv 0]

set file [lindex $argv 1]

spawn rsync -av $file root@$host:$file

expect {

"yes/no" { send "yes\r"; exp_continue }

"assword:" { send "$passwd\r" }

}

expect eof

## 执行脚本

[root@wy shell]# chmod +x 5.expect

[root@wy shell]# ./5.expect 192.168.219.128 /tmp/12.txt

spawn rsync -av /tmp/12.txt root@192.168.219.128:/tmp/12.txt

root@192.168.219.128's password:

sending incremental file list

sent 31 bytes  received 12 bytes  28.67 bytes/sec

total size is 5  speedup is 0.12

注:要想使用expect脚本去实现批量同步,首先要保证所有的机器密码一致,所有机器上的文件路径一致,标准化。


六、构建简易文件分发系统

构建文件分发系统

需求背景:对于大公司而言,肯定时不时会有网站或者配置文件更新,而且使用的机器肯定也是好多台,少则几台,

        多则几十甚至上百台。所以,自动同步文件是至关重要的。

实现思路:首先要有一台模板机器,把要分发的文件准备好,然后只要使用expect脚本批量把需要同步的文件分发到

        目标机器即可。

1、rsycn.expect脚本

[root@wy shell]# vim rsync.expect

#!/usr/bin/expect

set passwd "123456"

set host [lindex $argv 0]

set file [lindex $argv 1]

spawn rsync -av --files-from=$file / root@$host:/         #这是一个文件列表,必须是从根开始,写绝对路径

expect {

"yes/no" { send "yes\r"; exp_continue }

"assword:" { send "$passwd\r" }

}

expect eof

2、rsycn.sh脚本

[root@wy shell]# vim rsync.sh

#!/bin/bash

for ip in `cat ip.list`

do

  echo $ip

  ./rsync.expect $ip list.txt

done

3、加权限

[root@wy shell]# chmod +x rsync.expect

注:rsync.expect与rsync.sh必须在同一目录下


七、命令批量执行脚本

说明:现在能够批量同步文件了,但是还不行,因为我们配置文件更改完成之后,就需要启动服务,重启服务是需要登录远程机器上执行命令,所以执行命令还得需要去写一个执行命令的脚本。

1、exe.expect脚本

[root@wy shell]# vim exe.expect

#!/usr/bin/expect

set host [lindex $argv 0]

set passwd "123456"

set cm [lindex $argv 1]

spawn ssh root@$host

expect {

"yes/no" { send "yes\r"; exp_continue }

"assword:" { send "$passwd\r" }

}

expect "]*"

send "$cm\r"

expect "]*"

send "exit\r"

2、exe.sh脚本

[root@wy shell]# vim exe.sh

#!/bin/bash

for ip in `cat ip.list`

do

  echo $ip

  ./exe.expect $ip "w;free -m;ls /tmp"        #多个命令用分号隔开

done