我有以下期望脚本:
#!/usr/bin/expect
set hostname [lindex $argv 0]
set working_dir [lindex $argv 1]
set package [lindex $argv 2]
set tcl_test $working_dir/$package.tcl
set config $working_dir/$package.config
set logdir $working_dir/$package
set timeout 30
set prompt "\~\\\]\\\$"
eval spawn ssh $hostname
expect {
-re "(yes/no)" {send "yes\r"}
-re "password\:" {
interact {
-o
-re $prompt {send "export VARIABLE1=$working_dir\"\r"}
-re $prompt {send "issue-test-command -config $config -module $tcl_test\r"}
}
}
}
密码匹配和交互正常工作。一旦$ prompt匹配,就会发出环境变量export命令:
-re $prompt {send "export VARIABLE1=$working_dir\"\r"}
这是正确的,但后来不是继续前行:
-re $prompt {send "issue-test-command -config $config -module $tcl_test\r"}
读取相同的行,再次匹配模式并执行相同的命令。这导致发出相同命令的永久循环。
如何强制互动转移到下一行,或者使用不同的期望内置来实现我所追求的目标?
答案 0 :(得分:2)
想象一下,你正在向某人发出指示:
如果他们感到困惑,你不会感到惊讶。这就是你对Ex -re $prompt
多个分支所做的事情。但是Expect只接受你告诉它的第一条指令。
试试这个:
interact {
-o
-re $prompt {
send "export VARIABLE1=\"$working_dir\"\r"
send "issue-test-command -config $config -module $tcl_test\r"
}
}
顺便说一句:
exp_continue
send "yes\r"
export
命令答案 1 :(得分:1)
如果多次提供相同的模式,则只会执行一个关联的手臂。必须完整地写出更复杂的东西(例如,使用一个小状态机)。
但我认为你的代码太复杂了。你真正想要interact
的唯一地方就是你已经启动了程序,并且你可能需要一个多臂expect
的唯一地方就是当有多个事情可能发生时在交互中的那一点。让我们更简单地写一下,但是使用exp_continue
。 (我省略了变量的设置......)
eval spawn ssh $hostname
# Manage the login sequence, with its optional host check and optional password
# (that's optional in case someone decides to properly set up RSA keys)
expect {
-ex "(yes/no)" { # Exact match here
send "yes\r"
exp_continue
}
-ex "password:" { # Exact match here
send "$password\r"
exp_continue
}
-re $prompt { # RE match here
# Do nothing; fall out of the expect as we're now logged in...
}
}
# We're now at a prompt; make things work as desired
send "export VARIABLE1=\"$working_dir\"\r"
expect -re $prompt
send "issue-test-command -config $config -module $tcl_test\r"
# Now we're ready to let the user talk to the program...
interact