expect脚本

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

posted @ 2023-05-27 10:39  sjmuvx  阅读(611)  评论(0编辑  收藏  举报