0

我有以下期望脚本:

  • SSH 到主机
  • 如果需要,接受用户的密码
  • 一旦 ssh 成功(出现提示),设置环境变量
  • 再次返回提示符后,运行程序进行网络测试
  • 再次返回提示符后,退出期望并关闭 ssh 会话
#!/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 匹配,就会发出环境变量导出命令:

-re $prompt {send "export VARIABLE1=$working_dir\"\r"}

这是正确的,但不是继续前进:

-re $prompt {send "issue-test-command -config $config -module $tcl_test\r"}

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

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

4

2 回答 2

2

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

  1. 如果你看到红灯然后停下
  2. 如果你看到红灯然后走

如果他们感到困惑,你不会感到惊讶。这就是您对多个-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_continuesend "yes\r"
  2. 您在export命令上发送了错误数量的双引号
于 2012-09-24T08:18:32.757 回答
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
于 2012-09-24T10:24:47.963 回答