期望Interact一遍又一遍地读取匹配的行,而不会向前移动

时间:2012-09-24 04:02:47

标签: linux ssh command tcl expect

我有以下期望脚本:

  • SSH to host
  • 如果需要,接受用户的密码
  • 一旦ssh成功(出现提示),请设置环境变量
  • 再次返回提示,运行网络测试程序
  • 再次返回提示时,退出expect并关闭ssh session
#!/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"}

读取相同的行,再次匹配模式并执行相同的命令。这导致发出相同命令的永久循环。

如何强制互动转移到下一行,或者使用不同的期望内置来实现我所追求的目标?

2 个答案:

答案 0 :(得分:2)

想象一下,你正在向某人发出指示:

  1. 如果你看到红灯然后停止
  2. 如果你看到红灯,那就去
  3. 如果他们感到困惑,你不会感到惊讶。这就是你对Ex -re $prompt多个分支所做的事情。但是Expect只接受你告诉它的第一条指令。

    试试这个:

        interact {
            -o
            -re $prompt {
                send "export VARIABLE1=\"$working_dir\"\r"
                send "issue-test-command -config $config -module $tcl_test\r"
            }
        }
    

    顺便说一句:

    1. exp_continue
    2. 之后您遗失了send "yes\r"
    3. 您在export命令
    4. 上发送错误数量的双引号

答案 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