简体   繁体   English

为什么我的 Expect 脚本只回显未运行的命令?

[英]Why does my Expect script only echo the command not running?

I'm trying to automate some ssh process.我正在尝试自动化一些ssh过程。 I have my Expect code.我有我的 Expect 代码。 But my Expect code only echos/prints out the command.但是我的 Expect 代码只回显/打印出命令。 It doesn't actually run the command.它实际上并不运行命令。

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

So if I do所以如果我这样做

expect my_expect.exp

it just prints the command:它只是打印命令:

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)

What's wrong with my script?我的脚本有什么问题?

Because Tcl (and thus Expect) does not change the word boundaries when variables get substituted.因为当变量被替换时,Tcl(以及因此 Expect)不会改变单词边界。 You are trying to log into the host named exactly:您正在尝试登录到准确命名的主机:

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

spaces and all.空间和所有。

Logically, it does not make sense to put ssh options into a variable that holds the address.从逻辑上讲,将ssh选项放入保存地址的变量中是没有意义的。 May I suggest:我可以建议:

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) {}

Then然后

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

The {*} syntax is Tcl's "splat" operator that splits a word with spaces into the individual words. {*}语法是 Tcl 的“splat”运算符,它将带有空格的单词拆分为单个单词。 See https://tcl.tk/man/tcl8.6/TclCmd/Tcl.htm rule #5.参见https://tcl.tk/man/tcl8.6/TclCmd/Tcl.htm规则 #5。

Later, when you connect to the second machine, you're interpolating into a string, so the splat is not necessary:稍后,当您连接到第二台机器时,您将插入一个字符串,因此不需要 splat:

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

You might want to catch timeout events and abort the script:您可能想要捕获超时事件并中止脚本:

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

At the end of your script, after the run_engine script completes, you're still connected to addr2, so expect eof will not actually detect EOF on the spawned process.在您的脚本结束时,run_engine 脚本完成后,您仍然连接到 addr2,因此expect eof不会实际检测到生成的进程上的 EOF。 You'll timeout after 10 seconds and the Expect process will exit.您将在 10 秒后超时,并且 Expect 进程将退出。 For tidiness, you should:为了整洁,您应该:

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

If you think the run_engine script will take longer than 10 seconds, you should adjust the timeout variable before sending that command.如果您认为 run_engine 脚本将花费超过 10 秒的时间,则应在发送该命令之前调整超时变量。

Also, while developing an Expect script, you should turn on debugging:此外,在开发 Expect 脚本时,您应该打开调试:

exp_internal 1

That will show you what's going on behind the scenes, especially when it comes to seeing if your patterns are matching.这将向您展示幕后发生的事情,尤其是在查看您的模式是否匹配时。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM