【问题标题】:Why does my Expect script only echo the command not running?为什么我的 Expect 脚本只回显未运行的命令?
【发布时间】:2019-03-17 03:06:34
【问题描述】:

我正在尝试自动化一些ssh 进程。我有我的期望代码。但是我的 Expect 代码只回显/打印出命令。它实际上并没有运行命令。

#!/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)

我的脚本有什么问题?

【问题讨论】:

  • 一些不切实际的建议:使用 SSH 密钥身份验证会 a) 更安全,b) 允许您使用纯 shell 脚本而不是 expect,并且 c) 因此更容易维护。跨度>

标签: bash shell ssh automation expect


【解决方案1】:

因为 Tcl(以及 Expect)在变量被替换时不会改变单词边界。您正在尝试登录到确切命名的主机:

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 秒后超时,Expect 进程将退出。为了整洁,你应该:

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 秒,您应该在发送该命令之前调整超时变量。

另外,在开发 Expect 脚本时,您应该打开调试:

exp_internal 1

这将向您展示幕后发生的事情,尤其是在查看您的模式是否匹配时。

【讨论】:

    猜你喜欢
    • 2014-11-03
    • 1970-01-01
    • 2012-12-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多