expect实现交互式输入

Posted by DEVIN on Sun, Jun 18, 2023

1.常用命令

选项: -c:执行脚本前先执行的命令,可多次使用。 -d:debug模式,可以在运行时输出一些诊断信息,与在脚本开始处使用exp_internal 1相似。 -D:启用交换调式器,可设一整数参数。 -f:从文件读取命令,仅用于使用#!时。如果文件名为"-",则从stdin读取(使用"./-“从文件名为-的文件读取)。 -i:交互式输入命令,使用"exit"或"EOF"退出输入状态。 –:标示选项结束(如果你需要传递与expect选项相似的参数给脚本时),可放到#!行:#!/usr/bin/expect –。 -v:显示expect版本信息。

 1# 命令行参数 
 2# $argv,参数数组,使用[lindex $argv n]获取,$argv 0为脚本名字
 3# $argc,参数个数
 4set username [lindex $argv 1]  # 获取第1个参数
 5set passwd [lindex $argv 2]    # 获取第2个参数
 6 
 7set timeout 30 # 设置超时
 8 
 9# spawn是expect内部命令,开启ssh连接
10spawn ssh -l username 192.168.1.1
11 
12# 判断上次输出结果里是否包含“password:”的字符串,如果有则立即返回,否则就等待一段时间(timeout)后返回
13expect "password:"
14 
15# 发送内容ispass(密码、命令等)
16send "ispass\r"
17 
18# 发送内容给用户
19send_user "$argv0 [lrange $argv 0 2]\n"
20send_user "It's OK\r"
21# 执行完成后保持交互状态,控制权交给控制台(手工操作)。否则会完成后会退出。
22interact

2.例子

2.1自动telnet会话

 1#!/usr/bin/expect -f
 2set ip [lindex $argv 0 ]         # 接收第1个参数,作为IP
 3set userid [lindex $argv 1 ]     # 接收第2个参数,作为userid
 4set mypassword [lindex $argv 2 ] # 接收第3个参数,作为密码
 5set mycommand [lindex $argv 3 ]  # 接收第4个参数,作为命令
 6set timeout 10                   # 设置超时时间
 7 
 8# 向远程服务器请求打开一个telnet会话,并等待服务器询问用户名
 9spawn telnet $ip
10    expect "username:"
11    # 输入用户名,并等待服务器询问密码
12    send "$userid\r"
13    expect "password:"
14    # 输入密码,并等待键入需要运行的命令
15    send "$mypassword\r"
16    expect "%"
17    # 输入预先定好的密码,等待运行结果
18    send "$mycommand\r"
19    expect "%"
20    # 将运行结果存入到变量中,显示出来或者写到磁盘中
21    set results $expect_out(buffer)
22    # 退出telnet会话,等待服务器的退出提示EOF
23    send "exit\r"
24    expect eof

2.2其他

 1#!/usr/bin/expect
 2
 3expect {
 4	"Are you sure you want to continue connecting (yes/no)?" {send "yes\r"; exp_continue}
 5  "Password" {send "${PWD}\r"}
 6}
 7
 8expect "sftp>" {send "get /home/tools/123.zip\r"}
 9expect "sftp>" {send "quit\r"}
10
11expect eof
12EOF

参考文献

  1. expect - 自动交互脚本:https://xstarcd.github.io/wiki/shell/expect.html