为什么我的期望脚本仅回显未运行的命令?

时间:2018-10-11 23:18:26

标签: bash shell ssh automation expect

因此,我正在尝试使某些ssh流程自动化。我有我的期望代码。但是我期望的代码只会回显/销出命令。它实际上并没有运行命令。

#!/usr/bin/expect -f

set timeout 10
set usrnm "aaaaaa"
set pwd "pppppp"
set addr1 "xxx.cloud.xxx.com -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no"
set addr2 "xxx.xxxx.xxxx.com"

spawn ssh $usrnm@$addr1

expect {

    "(yes/no)?" {send "yes\r";exp_continue} 

    "password: " {send  "$pwd\r"}

}


expect "*#"
send "ssh $usrnm@$addr2\r"

expect {

    "(yes/no)?" {send "yes\r";exp_continue} 

    "password:" {send  "$pwd\r"}

}

expect "*#"

send "cd /tmp/myself/folder\r"

expect "*#"

send "./run_engine.sh test.py\r"

expect eof

#interact

所以我愿意

expect my_expect.exp

它只显示命令:

spawn ssh aaaaaa@xxx.cloud.xxx.com -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no (10s later) ssh aaaaa@xxx.xxxx.xxxx.com (10s later) cd /tmp/amz337/COAFALV (10s later) ./run_engine.sh test.py (exit)

我的脚本怎么了?

1 个答案:

答案 0 :(得分:1)

因为当变量被替换时,Tcl(并因此期望)不会更改单词边界。您正在尝试登录名称完全相同的主机:

xxx.cloud.xxx.com -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no

所有空格。

从逻辑上讲,将ssh选项放入保存地址的变量没有任何意义。我可以建议:

set addr1 "xxx.cloud.xxx.com"
set addr2 "xxx.xxxx.xxxx.com"
set ssh_opts($addr1) {-o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no}
set ssh_opts($addr2) {}

然后

spawn ssh {*}$ssh_opts($addr1) $usrnm@$addr1

{*}语法是Tcl的“ splat”运算符,用于将带有空格的单词拆分为单个单词。请参阅https://tcl.tk/man/tcl8.6/TclCmd/Tcl.htm规则#5。

稍后,当您连接到第二台计算机时,您将插入一个字符串,因此不需要splat:

send "ssh $ssh_opts($addr2) $usrnm@$addr2\r"

您可能想捕获超时事件并中止脚本:

expect {
    timeout      {error "timed-out connecting to $addr1"}
    "(yes/no)?"  {send "yes\r"; exp_continue} 
    "password: " {send  "$pwd\r"}
}

在脚本结尾,run_engine脚本完成后,您仍然连接到addr2,因此expect eof实际上不会在产生的进程中检测到eof。 10秒钟后您将超时,并且预期过程将退出。为使整洁,您应该:

send "./run_engine.sh test.py\r"
expect "*#"
send "exit\r"
# this prompt is from addr1
expect "*#"
send "exit\r"
# _now_ the spawned ssh process will end
expect eof

如果您认为run_engine脚本将花费超过10秒的时间,则应在发送该命令之前调整超时变量。

此外,在开发期望脚本时,您应该打开调试:

exp_internal 1

谢谢,将向您展示幕后情况,尤其是在查看模式是否匹配时。