Reputation: 67
I have the following expect script to:
#!/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"}
}
}
}
The password match and interact works correctly. As soon as $prompt is matched, the environment variable export command is issued:
-re $prompt {send "export VARIABLE1=$working_dir\"\r"}
This is correct, but then rather than moving on to the line:
-re $prompt {send "issue-test-command -config $config -module $tcl_test\r"}
The same line is read, the pattern is matched again and the same command is performed. This results in a permanent loop of issuing the same command.
How can I force interact to move on to the next line, or use a different expect built-in to achieve what I'm after?
Upvotes: 0
Views: 1655
Reputation: 137787
If you provide the same pattern multiple times, only one of the associated arms gets executed. More complex things have to be written out in full (e.g., with a little state machine).
But I think you're making that code rather too complex. The only place where you ever really want to interact
is once you've got the program started, and the only place where you might need a multi-arm expect
is when there are multiple things that might happen at that point in the interaction. Let's write it more simply, but with the use of exp_continue
. (I omit the setting of variables…)
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
Upvotes: 1
Reputation: 247210
Imagine you're giving instructions to someone:
You wouldn't be surprised if they get confused. That's what you're doing to Expect with multiple -re $prompt
branches. However Expect just takes the first instruction you tell it.
Try this:
interact {
-o
-re $prompt {
send "export VARIABLE1=\"$working_dir\"\r"
send "issue-test-command -config $config -module $tcl_test\r"
}
}
BTW:
exp_continue
after send "yes\r"
export
commandUpvotes: 2