expect简介
expect脚本语言是一种与需要用户交互的交互式程序或脚本对话的语言,其通过期待输入来工作,然后其将在没有任何用户交互的情况下发送响应。
安装:apt-get install expect
常用命令
命令 | 说明 |
---|---|
spawn | 启动新的交互进程,后面跟命令或者指定程序 |
expect | 等待进程输出作为expect脚本输入,支持正则 |
send | 向进程发送内容 |
interact | 允许与进程进行交互 |
exp_continue | 在expect中多次匹配就需要用到 |
send exp_send | 用于发送指定的字符串信息 |
send_user | 用来打印输出,相当于shell中的echo |
exit | 退出expect脚本 |
eof | expect执行结束, 退出 |
set | 定义变量 |
puts | 输出变量 |
set timeout | 设置超时时间 |
变量
设置变量:set myvar 5
传入参数设置变量:set myvar [lindex $argv 0]
。变量下标从0开始,和shell不同,shell的下标0是脚本名。
访问变量:$myvar
条件测试
通配符
expect {
"something" { send "send this\r" }
"*another" { send "send another\r" }
}
if-else
set NUM 1
if { $NUM < 5 } {
puts "\Smaller than 5\n"
} elseif { $NUM > 5 } {
puts "\Bigger than 5\n"
} else {
puts "\Equals 5\n"
}
spawn not found 的解决
脚本有两种执行方式:
- 将脚本作为sh的命令行参数:
sh x.sh
。当使用这种方法时,会导致#!/usr/bin/expect
失效,从而出现spawn not found
等错误。 - 将脚本作为具有执行权限的可执行脚本:
./x.sh
。使用这种方法,就能解决该问题。
实例
通过shell调用expect
#!/bin/bash
ip="172.16.22.131"
username="root"
password="123456"
# 指定执行引擎
/usr/bin/expect << EOF
set time 30
spawn ssh $username@$ip df -Th
expect {
"*yes/no" { send "yes\r"; exp_continue }
"*password:" { send "$password\r" }
}
expect eof # 退出此expect交互程序
EOF
跳板机、开发机登录
文件目录:
|-- login.exp
|-- servers
|-- serverName.cfg
|-- serverName.cmd
脚本:
#!/usr/bin/expect
#expect窗口自适应
trap {
set rows [stty rows]
set cols [stty columns]
stty rows $rows columns $cols < $spawn_out(slave,name)
} WINCH
# 0.堡垒机
set user "xxx"
set relay "relay.xxx.com"
# 1.指定要登录的服务器名称
set serverName [lindex $argv 0]
## 没有指定就弹出警告
if { $serverName == "" } {
send "请指定服务器名称\r"
exit
}
# 情况1:如果要登录的是堡垒机, 则尝试连接,并进入交互、输入密码
if { $serverName == "relay" } {
# catch用于捕获异常,如果catch返回0说明无异常
catch {spawn ssh $user@$relay}
interact
exit
}
# 情况2:通过堡垒机登录其他开发机
## 先登录堡垒机 ##
catch {spawn ssh $user@$relay}
## 加载服务器的host信息 ##
# serverName.cfg配置了$hostAndUser
source [file join [file dirname [info script]] servers/$serverName.cfg]
## 自动登录服务器 ##
expect {
"*yes/no" { send "yes\r"; exp_continue}
"*bash-xxx-ssl*" {
# 请求连接
send "ssh $hostAndUser \n"
# 输入密码,如果不需要密码,操作1秒就会退出
expect "*$hostAndUser's password:*" {
send "$password\n"
}
}
}
set timeout 2
# 登录开发机后执行的命令
# source、file join、file dirname、info script都是TCL命令
# []:其中的内容将被视为命令去执行
# source fileName:读取脚本并执行
# file join:将相对路径转换为绝对路径
# file dirname:返回文件所在的目录名称
# info script:返回被评估的脚本名称
# 所以 source [file join [file dirname [info script]] servers/common.cmd] 理解起来就是:1)info script当前脚本执行名称;2)当前脚本的目录名称;3)连接当前脚本目录名称和配置文件,组成配置文件的绝对路径
# 执行公共命令
# source [file join [file dirname [info script]] servers/common.cmd]
# 执行定制命令
source [file join [file dirname [info script]] servers/$serverName.cmd]
# 切换到控制台,正常手动输入模式
interact
配置文件serverName.cfg:
set hostAndUser "--matrix work@xx"
参考资料
https://www.cnblogs.com/shoufeng/p/11388060.html
https://wiki.tcl-lang.org/page/Expect
https://www.tcl-lang.org/man/expect5.31/expect.1.html
https://wiki.tcl-lang.org/page/file+join
https://wiki.tcl-lang.org/page/info+script
https://wiki.tcl-lang.org/page/Tcl+Tutorial+Lesson+5
标签:脚本,set,serverName,send,expect,file From: https://www.cnblogs.com/sjmuvx/p/17413497.html