**
EXPECT全解
**
Expect是Unix系统中用来进行自动化控制和测试的软件工具,由DonLibes制作,作为Tcl脚本语言的一个扩展,应用在交互式软件中如telnet,ftp,Passwd,fsck,rlogin,tip,ssh等等。该工具利用Unix伪终端包装其子进程,允许任意程序通过终端接入进行自动化控制;也可利用Tk工具,将交互程序包装在X11的图形用户界面中。
简单地说,expect是一个工具,可以根据用户设定的规则和系统进程进行自动化交互,例如远程登陆的密码输入、自动化的执行远程命令。
介绍
expect是建立在tcl(参见:Tcl/Tk快速入门 )基础上的一个工具,它可以让一些需要交互的任务自动化地完成。相当于模拟了用户和命令行的交互操作。
一个具体的场景:远程登陆服务器,并执行命令
登录时输入密码需要交互,bash脚本无法完成,可以使用expect来完成。安装
下面介绍两种安装方式
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, 不检查网站证书
- 原理与工作机制
首先使用 spawn 开启一个会话,然后使用 expect-send 对来执行交互式操作。
spawn 后面跟上一个命令操作,表示开启一个会话。expect 等待输出特定的字符串(通常是提示符),然后使用send 发送交互字符串。比如:
spawn ssh username@host # 远程登录
expect “*assword” # 提示为:”username@host’s password:”, 等待用户输入密码
send “${password}\r” # 这时使用send模拟用户输入密码的字符串,完成登录验证
- 基本语法介绍
脚本解释器
脚本中首先引入文件,表明使用的是哪一个shell
!/usr/bin/expect
set
设置会话超时时间为30s, 若不限制超时时间则应设置为-1
set timeout 30
set 还可以设置变量
使用变量语句: {param}({}用来避免param和后面的字符串拼接起来导致错误)
set param “param_str”
set param 1
spawn
spawn 后面跟一个命令,开启一个会话
spawn ${cmd} # for example : spawn su root
expect - send
expect 接收命令执行后的输出,然后和期望字符串匹配,若对应这执行相应的send来发送交互信息。
expect “ respond1\r”} # 这一行等同于下面两行
expect “ response1\r”
expect 可以有多个分支,就像switch语句一样。
expect
{
“
case2" {send "
case3" {send "$response3\r”}
}
结束符
expect eof :等待执行结束,若没有这一句,可能导致命令还没执行,脚本就结束了
interact : 执行完成后保持交互状态, 这时可以手动输入信息
注:expect eof 与 interact 二选一即可
接收参数
参数存在argv中,使用第一个参数如下:
set param0 [lindex argc表示参数个数,判断语句如下:
if {
argv0 … ”
exit
注:
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 1]
set password [lindex
argv 3]
set dest_file [lindex
src_file
host:
password\n”}
}
“*assword:”
{
send “$password\n”
}
}
expect “100%”
expect eof
chmod +x expect_scp
二.调用与执行scp各文件
vim scp.sh
!/bin/sh
list_file=
2
dest_file=
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
password
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 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 1]
set password [lindex
argv 3]
set dest_file [lindex
src_file
host:
password\n”}
}
“*assword:”
{
send “$password\n”
}
}
expect “100%”
expect eof
- 分发调用脚本
vim scp_executed.sh // 此脚本中,红色为上面登陆文件
!/bin/sh
list_file=
2
dest_file=
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
password
dest_file
done
- 远程主机密码文件
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 1]
set timeout 5
spawn ssh root@
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 //远程主机上,执行的动作,可以更多
- 远程主机密码文件
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
j
done
三.结合
vim all_scp_ssh
/root/auto/scp_all.sh