大数据兼云计算(王明龙)讲师-LINUX-DAY13-EXPECT

**

EXPECT全解

**


  Expect是Unix系统中用来进行自动化控制和测试的软件工具,由DonLibes制作,作为Tcl脚本语言的一个扩展,应用在交互式软件中如telnet,ftp,Passwd,fsck,rlogin,tip,ssh等等。该工具利用Unix伪终端包装其子进程,允许任意程序通过终端接入进行自动化控制;也可利用Tk工具,将交互程序包装在X11的图形用户界面中。
  简单地说,expect是一个工具,可以根据用户设定的规则和系统进程进行自动化交互,例如远程登陆的密码输入、自动化的执行远程命令。

1. 介绍
expect是建立在tcl(参见:Tcl/Tk快速入门 )基础上的一个工具,它可以让一些需要交互的任务自动化地完成。相当于模拟了用户和命令行的交互操作。 
一个具体的场景:远程登陆服务器,并执行命令 
登录时输入密码需要交互,bash脚本无法完成,可以使用expect来完成。

2. 安装
下面介绍两种安装方式

yum 安装
yum install -y expect

源码编译安装
expect 依赖于 tcl, 所以需要首先安装 tcl。可以使用rpm检查是否已经安装tcl:

rpm -qa | grep tcl

如果已安装,则会打印出tcl软件信息

安装过程参考:linux expect 安装 http://www.cnblogs.com/daojian/archive/2012/10/10/2718390.html 
tcl 地址:https://sourceforge.net/projects/tcl/files/Tcl/ 选择一个版本 
expect 地址:https://sourceforge.net/projects/expect/files/Expect/ 选择一个版本 
注意:wget 下载的时候需要加上 –no-check-certificate, 不检查网站证书

3. 原理与工作机制
首先使用 spawn 开启一个会话,然后使用 expect-send 对来执行交互式操作。 
spawn 后面跟上一个命令操作,表示开启一个会话。expect 等待输出特定的字符串(通常是提示符),然后使用send 发送交互字符串。比如:

spawn ssh username@host # 远程登录

expect "*assword" # 提示为:"username@host's password:", 等待用户输入密码
send "${password}\r" # 这时使用send模拟用户输入密码的字符串,完成登录验证

4. 基本语法介绍
脚本解释器
脚本中首先引入文件,表明使用的是哪一个shell

#!/usr/bin/expect
set
设置会话超时时间为30s, 若不限制超时时间则应设置为-1
set timeout 30

set 还可以设置变量

# 使用变量语句:$param 或者 ${param}({}用来避免param和后面的字符串拼接起来导致错误)
set param "param_str"
set param 1

spawn
spawn 后面跟一个命令,开启一个会话

spawn ${cmd} # for example : spawn su root
expect - send
expect 接收命令执行后的输出,然后和期望字符串匹配,若对应这执行相应的send来发送交互信息。

expect "$case1" {send "$respond1\r"} # 这一行等同于下面两行

expect "$case1"
send "$response1\r"

expect 可以有多个分支,就像switch语句一样。

expect 
{
    "$case1" {send "$response1\r"}
    "$case2" {send "$response2\r"}
    "$case3" {send "$response3\r"}
}

结束符
expect eof :等待执行结束,若没有这一句,可能导致命令还没执行,脚本就结束了 
interact : 执行完成后保持交互状态, 这时可以手动输入信息 
注:expect eof 与 interact 二选一即可

接收参数
参数存在argv中,使用第一个参数如下:

set param0 [lindex $argv 0]
1
2
$argc表示参数个数,判断语句如下:

if {$argc < 1} {
    #do something
    send_user "usage: $argv0 <param1> <param2> ... "
    exit
注:$argv0 是脚本名,但[lindex $argv 0]是第一个参数 param1, [lindex $argv 1]是第二个参数 param2, 以此类推 
send_user 用来显示信息到父进程(一般为用户的shell)的标准输出。

**

expect_scp
==========

**

一.解决scp交互

# vim expect_scp       解决交互执行的文件
---------------------------------------------------------------------------------------------
#!/usr/bin/expect  
set timeout 10  
set host [lindex $argv 0]  
set username [lindex $argv 1]  
set password [lindex $argv 2]  
set src_file [lindex $argv 3]
set dest_file [lindex $argv 4]  
spawn scp $src_file $username@$host:$dest_file  
expect {  
"(yes/no)?"  
   {  
    send "yes\n"  
    expect "*assword:" { send "$password\n"}  
 }  
"*assword:"  
{  
send "$password\n"  
}  
}  
expect "100%"  
expect eof
---------------------------------------------------------------------------------------------
chmod +x expect_scp


二.调用与执行scp各文件

# vim scp.sh
----------------------------------------------------------------------------------------------
#!/bin/sh
list_file=$1
src_file=$2
dest_file=$3
cat $list_file | while read line
do
   host_ip=`echo $line | awk '{print $1}'`
   username=`echo $line | awk '{print $2}'`
   password=`echo $line | awk '{print $3}'`
   echo "$host_ip"
   ./expect_scp $host_ip $username $password $src_file $dest_file
done
---------------------------------------------------------------------------------------------
chmod +x scp.sh

三.远程信息文件

# vim passwd.txt
---------------------------------------------------------------------------------------------
192.168.0.100 root redhat
---------------------------------------------------------------------------------------------


四.总执行脚本

# vim all_scp.sh
-------------------------------------------------------------------------------------------------
bash /root/scp.sh /root/passwd.txt 本地源文件路径 目标文件路径
......................可以很多scp 
-------------------------------------------------------------------------------------------------
chmod +x all_scp.sh




**

expect_ssh
==========

**

远程自动化执行脚本

1.实现远程执行动作脚本

# vim ssh.sh

#!/usr/bin/expect -f

set ipaddress [lindex $argv 0]

set passwd [lindex $argv 1]

set timeout 5

spawn ssh root@$ipaddress                              //这里主要是 @ 前的用户,是远程主机的用户,我这里全是 root

expect {

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

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

}

expect "*from*"

send "mkdir /tmp/wml\r"                                 //这是远程执行命令,可以很多条
send "touch /tmp/wml/www\r"

#send "exit\r"
expect {

"?assword:" {                    

send "$PASSWORD\r"     

exp_continue

}

}


2.调用执行动作与密码信息脚本,也是总执行脚本

# vim wml.sh

#!/bin/bash

for i in `awk '{print $1}' passwd.txt`

do

j=`awk -v I="$i" '{if(I==$1)print $2}' passwd.txt`             

expect /root/ssh.sh $i $j                  #执行动作脚本

done



3.远程IP与密码文件
# vim passwd.txt
192.168.0.102 redhat
192.168.0.104 redhat
192.168.0.106 redhat


**

expect_scp_ssh
==============

**

【 expect批量自动 《分发文件》 & 《执行文件》 文件 】

注意:1. 所有脚本必须在同一目录下编辑执行,否则不会成功
      2. 红色标记为主要改动的地方


一.分发文件

1.远程登陆脚本

# mkdir -p /root/auto/
# cd /root/auto/

# vim scp_login.sh                                  // 此脚本一般情况下,不需要改动
---------------------------------------------------------------------
#!/usr/bin/expect  
set timeout 10
set host [lindex $argv 0]
set username [lindex $argv 1]
set password [lindex $argv 2]
set src_file [lindex $argv 3]
set dest_file [lindex $argv 4]
spawn scp $src_file $username@$host:$dest_file
expect {
"(yes/no)?"
   {
    send "yes\n"
    expect "*assword:" { send "$password\n"}
 }
"*assword:"
{
send "$password\n"
}
}
expect "100%"
expect eof
------------------------------------------------------------------------


2. 分发调用脚本                        

# vim scp_executed.sh                           // 此脚本中,红色为上面登陆文件
---------------------------------------------------------------
#!/bin/sh
list_file=$1
src_file=$2
dest_file=$3
cat $list_file | while read line
do
   host_ip=`echo $line | awk '{print $1}'`
   username=`echo $line | awk '{print $2}'`
   password=`echo $line | awk '{print $3}'`
   echo "$host_ip"
   /root/auto/scp_login.sh $host_ip $username $password $src_file $dest_file
done
-----------------------------------------------------------------------


3. 远程主机密码文件

# vim scp_passwd.sh                                 // 此文件格式:IP  用户名 密码
-----------------------------------------------------------------------
192.168.0.100 root redhat
192.168.0.104 root redhat
192.168.0.106 root redhat
-----------------------------------------------------------------------



4.总执行scp脚本

# vim scp_all.sh                                     // 此脚本格式:调用文件 密码文件 源文件目录 目标目录
----------------------------------------------------------------------
/root/auto/scp_executed.sh /root/auto/scp_passwd.sh /root/iptables.sh /root/
/root/auto/scp_executed.sh /root/auto/scp_passwd.sh 本地源文件路径 目标文件路径
----------------------------------------------------------------------






二.执行文件

1.远程登陆脚本

# vim ssh_login.sh
----------------------------------------------------------------------------------
#!/usr/bin/expect -f
set ipaddress [lindex $argv 0]
set passwd [lindex $argv 1]
set timeout 5
spawn ssh root@$ipaddress
expect {
"yes/no" { send "yes\r";exp_continue }
"password:" { send "$passwd\r" }
}
expect "*from*"
send "/root/iptables.sh\r"
#send "exit\r"
expect {
"?assword:" {            
send "$PASSWORD\r"
exp_continue
}
}
---------------------------------------------------------------------------------
                                                        // 上面脚本红色解析:set timeout 5     //在远程主机执行时,停顿的秒数,可以调整
                                                                            root            //本地主机的身份,可以是其它用户
                                                                            /root/iptables.sh   //远程主机上,执行的动作,可以更多

2. 远程主机密码文件

# vim ssh_passwd.sh                                       // 此脚本格式:IP 用户名 密码
---------------------------------------------------------------------------------
192.168.0.100 redhat
192.168.0.104 redhat
192.168.0.106 redhat
---------------------------------------------------------------------------------


3.总执行ssh文件

# vim ssh_all.sh                                           // 前两个红色标记为ssh的密码文件,后一个是ssh的登陆文件   
--------------------------------------------------------------------------------
#!/bin/bash
for i in `awk '{print $1}' "/root/auto/ssh_passwd.sh"`
do
j=`awk -v I="$i" '{if(I==$1)print $2}' "/root/auto/ssh_passwd.sh"`
expect /root/auto/ssh_login.sh $i $j
done
--------------------------------------------------------------------------------




三.结合

# vim all_scp_ssh
--------------------------------------------------------------------------------
/root/auto/scp_all.sh
/root/auto/ssh_all.sh
--------------------------------------------------------------------------------

# chmod +x /root/auto -R
# /root/auto/all_scp_ssh
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

IT灵魂摆渡者

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值