在与服务器登录执行任务的时候,需要执行某项任务,这是最正常不过了;如何有效自动的执行呢?这里介绍自动交互脚本expect的使用。


expect是一个简单的工具语言,如要工作就是进行自动化的人机交互。它的作者对Expect的定义:是一个实现自动交互功能的软件套件(a software suite for automating interactive tools),使用expect,它能帮助我们在合适的情景下进行合适的交互。


expect的核心是spawn、 expect、 send、 set


spawn         ## 调用要执行的命令
expect        ##等待命令提示信息的出现,也就是捕捉用户输入的提示
send         ##发送需要交互的值,替代了用户手动输入内容
set          ##设置变量值
interact       ##执行完成后保持交互状态,把控制权交给控制台,这个时候就可以手工操作了。如果没有这一句登录完成后会退出,而不是留在远程终端上。
expect eof     # 这个一定要加,与spawn对应表示捕获终端输出信息终止,类似于if....endif
expect脚本必须以interact或expect eof结束,执行自动化任务通常expect eof表示脚本执行完成。


1、expect的安装,yum 安装可以帮助解决依赖,如果源码安装需要安装

yum -y expect


2、案例说明

2.1、自动登录系统并执行任务

#!/usr/bin/expect               
set host "192.168.16.69"
set passwd "fgjh123."                            ##设置变量
spawn ssh root@$host                            ##调用执行命令
expect {                                     ##等待命令出现
        "yes/no" {send "yes\r"; exp_continue}    ##发送交互值,yes
        "password:" {send "$passwd\r"}       ##输入密码
        }
expect "]*"                                ##获取当前的终端的命令行提示符
send "uptime\r"                            ##执行uptime 命令,\r是换行
expect "]*"
send "exit\r"                                ##执行完命令后,退出当前终端。
expect eof

                            

脚本的执行过程:

# ./login.expect
spawn ssh root@192.168.16.69
root@192.168.16.69's password:
Last login: Fri Dec  4 21:30:27 2014 from 192.168.16.170
# uptime
 21:31:19 up  1:14,  1 user,  load average: 0.32, 0.18, 0.17
# exit
登出
Connection to 192.168.16.69 closed.


可以看到整个脚本的执行过程,另外需要说明的是,这个shell 脚本一样需要增加执行权限(x)


2.2、使用传递参数

#!/usr/bin/expect               
set user [lindex $argv 0]          #参数1,用户名
set passwd [lindex $argv 1]     #参数2,用户密码
set host [lindex $argv 2]          #参数3,远程主机ip或者主机名
set cmd [lindex $argv 3]          #参数4,执行命令
spawn ssh $user@$host
expect {
        "yes/no" {send "yes\r"; exp_continue}
        "password:" {send "$passwd\r"}
        }
expect "]*"
send "$cmd\r"
expect "]*"
send "exit\r"
expect eof

脚本的执行是在脚本后面依次写对应的参数,用户名、用户密码、主机ip、执行命令,参数之间使用空格隔开


执行如下:

# ./login.expect root 123123. 192.168.16.69 uptime
spawn ssh root@192.168.16.69
root@192.168.16.69's password:
Last login: Fri Dec  4 21:31:19 2015 from 192.168.16.170
# uptime
 21:41:22 up  1:24,  1 user,  load average: 0.15, 0.09, 0.13
# exit
登出
Connection to 192.168.16.69 closed.


以上的简单了解了expect的使用,还可以结合shell命令一起使用,构建一个简单的文件分发系统。


3、简单的文件分发系统

对大批量的主机同步文件,首先需要有一台模版的机器,把需要分发的文件都准备好,然后用expect脚本批量同步到目标的远程主机;核心的命令:

rsync –av –file-from=list.txt / root@host:/


这里使用rysnc的,首先会建立ip.list这是主机的ip ;

list.txt是要同步的文件的路径;

rsync.expect是自动同步的脚本;

rsync.sh是用来获取多台主机的ip和同步的目录的路径登录。


脚本如下:


执行的主机:

# vim ip.list

192.168.17.14
192.168.17.11

~                 

同步的文件路径

# vim list.txt

/tmp/rsync
/tmp/rsync001

~               

同步脚本:

vim rsync.expect

#!/usr/bin/expect
set host [lindex $argv 0]
set user "root"
set passwd "fgjh123."
set file [lindex $argv 1]
spawn rsync -av --file-from=$file / $user@$host:/
expect {
        "yes/no" {send "yes\r"}
        "password" {send "$passwd\r"}
        }
expect eof
vim rsync.sh
#!/bin/bash
for ip in `cat ip.list`
do
echo $ip
[ -x rsync.expect ] || chmod a+x rsync.expect
./rsync.expect $ip list.txt
done

~       

然后执行rsync.sh脚本就可以 。



4、批量执行程序

需要做多台机器上执行程序,也可以使用如上的方法

# vim exe.expect

#!/usr/bin/expect
set host [lindex $argv 0]
set user "root"
set passwd "fgjh123."
set cmd [lindex $argv 1]
spawn ssh $user@$host
expect {
        "yes/no" {send "yes\r"}
        "password" {send "$passwd\r"}
        }
expect "]*"
send "$cmd\r"
expect "]*"
send "exit\r"
expect eof

编写要用于循环ip的exe.sh

# vim exe.sh

#!/bin/bash
for ip in `cat ip.list`
do
echo $ip
[ -x exe.expect ] || chmod a+x exe.expect
./exe.expect $ip 'free -m;uptime'
done

    

思路都是通过循环ip来实现。

以上都是介绍一种思想,具体的应用需要结合实际情况。