Ssh 在不超时的情况下退出expect{}
我正在努力解决在ssh中自动键入密码之类的经典问题 其他人我都在黑暗中跌跌撞撞。最后,我拼凑了一个脚本,这是一种工作:Ssh 在不超时的情况下退出expect{},ssh,scripting,expect,Ssh,Scripting,Expect,我正在努力解决在ssh中自动键入密码之类的经典问题 其他人我都在黑暗中跌跌撞撞。最后,我拼凑了一个脚本,这是一种工作: #!/usr/bin/expect -f # command line args set user_at_host [lrange $argv 0 0] set password [lrange $argv 1 1] set timeout 1 # ssh command spawn ssh -S ~/.ssh/tmp.$user_at_host -M -N -f $us
#!/usr/bin/expect -f
# command line args
set user_at_host [lrange $argv 0 0]
set password [lrange $argv 1 1]
set timeout 1
# ssh command
spawn ssh -S ~/.ssh/tmp.$user_at_host -M -N -f $user_at_host
# deal with ssh prompts
expect {
"*yes/no*" { send "yes\r" ; exp_continue }
"*assword:" { send "$password\r" ; exp_continue }
}
此脚本仅因超时1
行而终止,如果没有它,它将挂起,并且仅通过用户交互(^C
)终止
当spawn
行是一个直接的ssh命令时,脚本立即终止,但是这是错误的。可能不同的是-f
选项使其在后台运行(但我尝试了没有脚本的脚本,但没有结果)
我读到,interactive
或expect eof
可能会有帮助,但我无法找到正确的咒语
我的问题(我想)是如何让产生后台进程的expect脚本在没有超时的情况下终止
编辑:我应该预料到(没有双关语)会出现“使用无密码ssh身份验证”的答案。虽然这是一个合理的建议,但在我的场景中它不是合适的解决方案:在受信任的环境中自动测试普通安装的系统,在这种环境中,向映像添加受信任的密钥是不可取/不可能的。此循环:
expect {
"*yes/no*" { send "yes\r" ; exp_continue }
"*assword:" { send "${password}\r" ; exp_continue }
}
除超时或EOF外,不能以任何方式终止;两条匹配的行将exp\u继续
,因此再次循环
进入背景意味着基本上是分叉;父节点死亡,子节点继续连接
就我个人而言,我会以不同的方式解决交互元素:
expect {
"*yes/no*" { send "yes\r" ; exp_continue }
"*assword:" { send "${password}\r" }
}
expect $the_prompt
send "exit\r"
expect eof
更新
我没有注意到您正在通过ssh发送命令。我想你所需要的就是:
spawn ssh a@b foo bar baz
expect {
"*yes/no*" { send "yes\r" ; exp_continue }
"*assword:" { send "${password}\r" }
eof
}
当
foo
命令完成时,您会点击eof
。好的,所以我找到了一个似乎有效的排列--
首先,我需要一个包装器脚本,它将在完成时给出指示:
#!/bin/bash
"$@"
echo "done"
然后expect脚本变为:
#!/usr/bin/expect -f
set user_at_host [lrange $argv 0 0]
set password [lrange $argv 1 1]
# no need for timeout 1
set timeout 60
# use the wrapper
spawn wrapper ssh -S ~/.ssh/tmp.$user_at_host -M -N -f $user_at_host
expect {
"*yes/no*" { send "yes\r" ; exp_continue }
"*assword:" { send "$password\r" ; exp_continue }
# use the wrapper
"done" { exit }
}
感谢道格拉斯·利德(投赞成票)和格伦·杰克曼(投赞成票)的有益建议。我将很乐意不接受这个答案,并接受任何更优雅的答案,也许是一个废除包装器脚本的答案
谢谢大家的关注。我这样做:
set user "****"
set host "127.0.0.1"
spawn shh $user@$host
expect "password: "
send "**??54"
expect "$"
interact
(这回答了您如何使用交互方法)有没有办法在*密码:
之后立即退出?当我尝试用其他任何东西替换exp\u continue
时,它确实立即退出,但似乎没有发送${password}
。可能是睡眠1
或期望eof
或等待
?抱歉,我在犹豫,也许你可以帮我减少我必须测试的排列数:等待eof
/睡眠1
是否在期望{…}
循环的内部或外部?我会删除密码exp_continue语句。然后试着在expect小组之后加入sleep或其他小组。谢谢你的帮助。你的建议为我的解决方案提供了一些重要的线索。这并没有解决我的问题,但给了我一个重要的线索:完成后我需要某种提示。看看我自己的答案。谢谢