bash - 为什么我的 Expect 脚本只回显未运行的命令?
问题描述
我正在尝试使某些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)
我的脚本有什么问题?
解决方案
因为当变量被替换时,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 秒后超时,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
这将向您展示幕后发生的事情,尤其是在查看您的模式是否匹配时。
推荐阅读
- java - AssertJ Swing 无法在一台 Windows 10 机器上运行
- javascript - javascript中的过滤器数组在多个过滤器值的情况下未找到时删除项目
- visual-studio-code - TreeViewItem 项目上的命令单击,VSCode 扩展
- php - 将数据从控制器传递到刀片视图
- javascript - 使用 Express.js 响应计算量大的请求
- css - XSL 选择样式文本和 td
- javascript - 检查其他对象中是否存在键
- mongodb - 如何使用 MongoDB 聚合有条件地匹配搜索表单中不为空的字段?
- sql - 根据另一列获取最新值并独立对另一列求和
- javascript - 使用 Javascript 添加到嵌套在另一个 div 中的 div