摘要:在配置免密登陆时,需要进行服务器或用户之间的切换并执行相应的命令,经过长时间的尝试,对成果做个记录。
expect基于tcl的,是一个实现自动交互的脚本工具。除支持Unix/Linux平台外,它还支持Windows平台,是为系统管理和软件测试方面自动交互类需求而产生的。
expect是一个免费的编程工具语言,用来实现自动和交互式任务进行通信,而无需人的干预,是一个用来实现自动交互功能的软件套件。
安装expect
系统需已安装tcl:whereis tcl
yum install -y expect
使用 spawn 开启一个会话,然后使用 expect-send 对来执行交互式操作。
spawn 后面跟上一个命令操作,表示开启一个会话。
expect 等待输出特定的字符串(通常是提示符)。
send 发送交互字符串。
#!/usr/bin/expect
$argc参数个数
$argv 0 第一个命令行参数,以此类推(带空格)
$argv0 是脚本名(不带空格)
# $argc,$argv 0,$argv 1 ... $argv n
if {$argc<2} {
send_user "Usage: $argv0 login passwaord.n "
exit 1
}
send_user 用来显示信息到父进程(一般为用户的shell)的标准输出,相当于Linux shell中的echo
send_user "string"
set timeout命令设置后面所有的expect命令的等待响应的超时时间(-l参数用来关闭任何超时设置)。
设置会话超时时间为30s, 若不限制超时时间则应设置为-1
set timeout 30
设置变量并赋值
set param "param_str"
设置变量为命令行参数
set password [lindex $argv 0]
spawn 后面跟一个命令,开启一个会话或进程,expect和send都将在这个会话或进程里面运行。
而命令实际上是以衍生子进程的方式运行。
spawn su root
expect 接收命令执行后的输出,然后和期望字符串匹配,若对应这执行相应的send来发送交互信息。
expect等待输出中输出特定的字符,通常是一个提示符,然后发送特定的响应。
主要运用场景是接收Linux系统控制台的提示信息,如果提示信息中包含expect后面的字符串,而执行send后面的动作,即命令
单一分支模式:
expect "$case1" {send "$response1\r"}
多个分支模式:类似switch语句
expect {
"$case1" {send "$response1\r"}
"$case2" {send "$response2\r"}
"$case3" {send "$response3\r"}
timeout { }
}
判断及正则表达式运用
使用了-re参数,表示指定的的字符串是一个正则表达式
在一个正则表达时中,可以在()中包含若干个部分并通过expect_out数组访问它们
expect -re "\[(.*)]:"
if {$expect_out(1,string)!="/bin/tcsh"} {
send "/bin/tcsh" }
send " "
expect eof
expect eof :等待执行结束,若没有这一句,可能导致命令还没执行,脚本就结束了
interact : 执行完成后保持交互状态, 这时可以手动输入信息
注:expect eof 与 interact 二选一即可
set param0 [lindex $argv 0]
if {$argc < 1} {
#do something
send_user "usage: $argv0 <param1> <param2> ... "
exit }
proc do_console_login {login pass} {
..............
}
while ($done) {
................
}
switch -- $timeout_case {
0 {
...............
}
1 {
...............
}
2 {
...............
}
}
incr timeout_case
保存为脚本文件remote_root_command.exp
#!/usr/bin/expect
if {$argc < 4} {
#do something
send_user "usage: $argv0 <remote_user> <remote_host> <remote_pwd> <remote_root_pwd>"
exit
}
set timeout -1
set remote_user [lindex $argv 0] # 远程服务器用户名
set remote_host [lindex $argv 1] # 远程服务器域名
set remote_pwd [lindex $argv 2] # 远程服务器密码
set remote_root_pwd [lindex $argv 3] # 远程服务器根用户密码
# 远程登录
spawn ssh ${remote_user}@${remote_host}
expect "*assword:" {send "${remote_pwd}\r"}
expect "Last login:"
# 切换到 root
send "su\r"
expect "*assword:" {send "${remote_root_pwd}\r"}
# 执行关闭防火墙命令
send "service iptables stop\r"
send "exit\r"
send "exit\r"
expect eof
执行命令:./remote_root_command.exp <remote_user> <remote_host> <remote_pwd> <remote_root_pwd>
#!/bin/bash
pwd='123456'
ls_date=`date +%Y-%m-%d`
expire_me="R_rhp-report_ALL_daily_"${ls_date}".txt"
curdir=$(cd $(dirname $0); pwd)
echo $pwd
echo $expire_me
echo $curdir
/usr/bin/expect <<-EOF
spawn sftp kaifatest@reports.afilias.info;
expect {
"kaifatest@reports.afilias.info's password:" {send_user $pwd;send "$pwd\r";exp_continue}
"sftp>" {send "get $expire_me $curdir\rquit\r";exp_continue}
}
expect eof;
EOF
exit
脚本解释说明
#!/bin/bash => shell脚本执行
全部expect:#!/usr/bin/expect
/usr/bin/expect <<-EOF => 此处开始执行expect脚本,记住EOF前面的“-”
expect中最关键的四个命令是send,expect,spawn,interact。
send:用于向进程发送字符串
expect:从进程接收字符串
spawn:启动新的进程
interact:允许用户交互
spawn命令是Expect的初始命令,它用于启动一个进程,之后所有expect操作都在这个进程中进行,如果没有spawn语句,整个expect就无法再进行下去了
expect 是针对需要交互的地方进行自动发送消息,{ 大扣号前面必须要有空格,前面引号内的内容是交互界面等待输入的匹配字串,{} 内的是交互输入的内容,
send_user 等同于shell里的echo 显示用,
send 发送数据,最后的\r必需,说明输入密码并回车了
exp_continue 继续处理下一步命令
进入sftp后,需要获取所需文件并退出,因为都是在"sftp>"下面处理,所以两个命令放一起:
"sftp>" {send "get $expire_me $curdir\rquit\r";exp_continue}
expect eof =>此命令和spawn 是匹配的,spawn进程结束后会向expect发送eof,表示退出spwan
EOF 解除expect脚本执行,跳出到shell执行环境
收藏