一、Expect简介

       在远程服务器执行某项任务,这是最正常不过了,如何有效自动的执行呢?这里介绍自动交互脚本expect的使用。

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

     Expect是一种能够按照脚本内容里面设定的方式与交互式程序进行“会话”的程序。根据脚本内容,Expect可以知道程序会提示或反馈什么内容以及什么是正确的应答。

它是一种可以提供“分支和嵌套结构”来引导程序流程的解释型脚本语言。 shell功能很强大,但是不能实现有交互功能的多机器之前的操作,例如ssh和ftp.而expect可以帮助我们来实现.

     Expect:一个实现自动交互功能的软件套件,基于Tcl的一种脚本语言,具有简单的语法;

功 能 :实现自动登录远程机器,并自动执行命令和shell脚本结合,可以实现完全自动化;

注 意 :使用不带密码的密钥验证也可以实现该功能;没有密钥就只能用对方账号和密码了

二、Expect使用

1、安装

[root@localhost ~]# yum install expect

Dependencies Resolved

=========================================================================================
 Package           Arch              Version                       Repository       Size
=========================================================================================
Installing:
 expect            x86_64            5.44.1.15-5.el6_4             base            256 k
Installing for dependencies:
 tcl               x86_64            1:8.5.7-6.el6                 base            1.9 M

Transaction Summary
=========================================================================================
Install       2 Package(s)

2、使用方法

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

这些命令是进入expect环境后才可以执行的expect内部命令,若没有装expect或者直接在默认的SHELL下执行是无法使用的,找不到它在哪;

spawn    ##调用要执行的命令或脚本

主要功能:传递交互指令,它主要的功能是给命令运行进程加个壳,用来传递指令。 


expect    ##等待命令提示信息的出现,也就是捕捉用户输入的提示

主要功能:判断输出结果是否包含某项字符串,没有则立即返回,否则就等待一段时间后返回,等待时间通过timeout进行设置


send       ##发送需要交互的值,替代了用户手动输入内容

主要功能:执行交互动作,将交互要执行的动作进行输入给交互指令;

               命令字符串结尾要加上"r",如果出现异常等待的状态可以进行核查


set          ##设置变量值

set timeout 30

设置超时时间,单位是秒,如果设为timeout -1 意为永不超时


interact    ##执行完成后保持交互状态,把控制权交给控制台,这个时候就可以手工操作了。

如果没有这一句登录完成后会退出,而不是留在远程终端上。用在登录命令后,结尾 


exp_continue   继续执行接下来的交互操作


expect eof   ##这个一定要加,与spawn对应表示捕获终端输出信息终止,类似于if....endif

    标示子进程已结束的标示符;如果没有eof,可能在子进程没有结束前就退出或是执行完进程后待在远程终端不退出来了;

expect脚本必须以interact或expect eof结束,执行自动化任务通常expect eof表示脚本执行完成。


#!/usr/bin/expect

   提示操作系统脚本内的东西是用哪个shell执行的,而expect和bash·win的cmd差不多;

   注意:这一行需要在脚本的第一行。 


$argv 参数数组

   expect脚本可以接受从bash传递过来的参数.可以使用[lindex $argv n]获得;

            n从0开始,分别表示第一个,第二个,第三个……参数

比如:

set passwd [lindex $argv 0]    就可以在下面用$passwd调用

spawn ssh root@1.1.1.1  $passwd   当执行时在后面输入密码,比密码放在文件 

三:简单举例

1、通过expect实现非交互式ssh远程登录,登录后不退出

#!/usr/bin/expect
 
set host "192.168.1.1"                       #远程终端的IP
set passwd "123456"                          #远程终端root密码
 
spawn ssh  root@$host                        #登录远程
 
expect {                                     #子进程
"yes/no" { send "yes\r"; exp_continue}       #登录后遇到yes/no字样,输入yes回车
"assword:" { send "$passwd\r" }              #遇到password字样,输入变量,回车 
}                                       
interact                                     #保持交互,不退出
[root@localhost tmp]# ./test 
spawn ssh root@10.0.250.34
root@10.0.250.34's password: 
Last login: Tue Jan 12 11:19:37 2016 from 10.0.248.17

2、通过调用bash的位置参数实现ssh远程登录

[root@localhost tmp]# cat 4test 
#!/usr/bin/expect
set ipaddress [lindex $argv 0]
set user [lindex $argv 1]
set passwd [lindex $argv 2]
set timeout 30
spawn ssh $user@$ipaddress
expect {
"yes/no" { send"yes\r";exp_continue }
"password:" {send "$passwd\r" }
}
interact
[root@localhost tmp]# ./4test 10.0.250.34 root dy\!\(13243225022313\) #这里符号要转义
spawn ssh root@10.0.250.34
root@10.0.250.34's password: 
Last login: Tue Jan 12 14:46:27 2016 from 10.0.248.17
[root@BriefServer ~]# hostname
BriefServer

3、登陆后,执行命令然后退出

[root@EarthServer ~]# echo $(hostname)
EarthServer
[root@EarthServer ~]# exit
logout
Connection to 10.0.250.35 closed.
[root@localhost tmp]# 
[root@localhost tmp]# cat 3test 
#!/usr/bin/expect
set ipaddress "10.0.250.35"
set passwd "HYldy!(18250822313)"
set timeout 30
spawn ssh root@$ipaddress
expect {
"yes/no" {send "yes\r";exp_continue}
"password:" {send "$passwd\r"}
}
expect "]*"
send "echo \$(hostname)\r"

interact

[root@localhost tmp]# ./3test 
spawn ssh root@10.0.250.35
root@10.0.250.35's password: 
Last login: Tue Jan 12 16:55:33 2016 from 10.0.248.17
[root@EarthServer ~]# echo $(hostname)
EarthServer

在脚本中引用expect脚本:expect -c ""

#!/bin/bash 
username="root"
hostname="192.168.137.28"
password="redhat"
expect -c "  #-c 实现调用
##注意凡是-c后调用的内容,如果带有""双引号的话,必须用\进行转义,否则报错
set timeout 10
spawn ssh \"$username@$hostname\"
expect {
\"yes/no\" {send \"yes\r\";exp_continue}
 \"password:\" {send \"$password\r\"}
}
expect \"]#\"
send \"ll\r\"
interact
exit
"