#!/usr/bin/expect
开启交互命令
spawn ssh $user@$ip
模式匹配
一般情况expect跟在 spawn后面 用来匹配spawn启动的命令的输出 并使用send给命令提供输入
也可以直接在命令行里进入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