expect

脚本开始

#!/usr/bin/expect

开启交互命令

spawn ssh $user@$ip

模式匹配

一般情况expect跟在 spawn后面 用来匹配spawn启动的命令的输出 并使用send给命令提供输入

也可以直接在命令行里进入expect解析器里,直接测试expect的模式匹配

expect单模式

expect 后面可以是单一分支

expect "hi" {send "You said hi\n"}

expect多模式

expect 后面也可以是多分支,有任何一个分支出现就可以,不分先后顺序, 有多个分支时,可以用{} 将所有的分支括起来,就可以换行了,单左{ 必须和expect 在同一行 expect "hi" { send "You said hi\n" } "hehe" { send "Hehe yourself\n" } "bye" { send "Good bye\n" }

expect eof

spawn启动的命令结束时,会返回eof, 脚本结尾的 expect eof 表示模式匹配 命令结束的eof 是一种特殊的模式匹配

exp_continue

exp_continue 在 expect 分支中出现,表示再次进入该expect,进行重复等待expect后面的分支出现,没有exp_continue时,执行完匹配的模式后,退出该expect,程序往后执行 expect "hi" {send "You said hi\n";exp_continue}

设置超时

设置超时时间 set timeout 10 #单位 秒

set timeout -1 # 用不超时

set timeout # 默认是10s

超时时间是指每个expect的超时时间, 如果expect后面有 exp_continue 会重置超时时间

变量

变量赋值

使用set 给变量赋值 变量不用声明,可以直接进行赋值 set password 123456wht # 默认就是字符串 set password "123456wht" # 我喜欢用双引号引住

使用变量

$password 直接引用 也可以把引用放到双引号里 expect "password" { send "$password\n" }

使用参数

set ip [lindex $argv 0] #第一个参数 set user [lindex $argv 1] #第二个参数

puts "${argv0}" # 获得命令名称

puts "$argv0" # 获得命令名称

puts "参数个数${argc}" puts [lindex ${argv} 0] #第一个参数 puts [lindex ${argv} 1] #第二个参数

脚本结束

expect eof 和 interact 都是放到脚本的最后 interact表示把交互主动权从expect交给用户,让用户进行后续的与程序的交互 expect eof表示 等待由spawn开启的程序结束

exit 直接结束交互 退出expect

执行shell命令

在expect中(其实是tcl种) 使用中括号括起来要执行的内容,并返回执行结果

常见有 set username [lindex ${argv} 0]

lindex是tcl种的一个命令: 从指定的list种取出 指定位置的元数

set password_file [exec sh -c "echo file_name"]

sh -c "xxxx命令字符串" 使用sh执行指定的命令字符串

调试脚本

expect -d expect脚本文件名称 会打印很详细的交互内容

在shell中调用 expect

expect <<-EOF set timeout 10 spawn ssh $user@$ip expect { "yes/no" { send "yes\n";exp_continue } "password" { send "$password\n" } } expect "]#" { send "useradd test\n" } expect "]#" { send "exit\n" } expect eof EOF

上面的一整段时shell的一行命令而已

使用expect来执行后面的字符串 <<-EOF 在shell中可以输入多行字符串,且是以EOF结尾,两种成对出现,将EOF换成abc也是一样的; 如果"<<-EOF"中没有"-"(形式:<<EOF) 结尾可以是eof/EOF 会跟expect eof冲突

疑问

在shell内执行时,可以直接使用shell定义的变量???

试了下可以耶

 

其他语法

支持 switch

`#!/usr/bin/expect set color [lindex $argv 0] switch $color { apple { puts "apple is blue" } banana { puts "banana is yellow " }

}`

支持if

#!/usr/bin/expect set test [lindex $argv 0] if { "$test" == "apple" } { puts "$test" } else { puts "not apple" }

支持for/ foreach

#!/usr/bin/expect for {set i 0} {$i<4} {incr i} { puts "$i" }

支持while

#!/usr/bin/expect set i 1 while {$i<4} { puts "$i" incr i }

支持 proc 定义函数

#!/usr/bin/expect proc test {} { puts "ok" } test

都跟c语言语法类型,注意expect里没有小括号,所有其他语言用到小括号的都使用大括号代替

 

 

参考

http://blog.leanote.com/post/wkf19911118@gmail.com/shell%E7%BC%96%E7%A8%8B%E4%B9%8Bexpect

https://www.cnblogs.com/ph829/p/5091302.html

https://yearn.xyz/posts/techs/tcl-%E8%AF%AD%E8%A8%80%E7%AE%80%E4%BB%8B/

posted @ 2025-03-18 20:25  halu126  阅读(33)  评论(0)    收藏  举报