我正在努力解决在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 $user_at_host
# deal with ssh prompts
expect {
"*yes/no*" { send "yes\r" ; exp_continue }
"*assword:" { send "$password\r" ; exp_continue }
}
此脚本仅通过timeout 1
行终止,如果没有它,它只会挂起,并且只会通过用户交互(^C
)终止。
当spawn
行是一个直接的ssh命令时,脚本会立即终止,但这是not your straight forward ssh。可能不同的是-f
选项使其在后台运行(但我尝试了没有它的脚本无效)。
我认为interact
或expect eof
可能有所帮助,但我无法找到真正实现此目的的正确咒语。
我的问题(我认为)是如何制作一个期望脚本,产生后台进程,终止而不会超时?
编辑:我应该预期(没有双关语意)“使用无密码ssh身份验证”答案。虽然这是一个合理的建议,但在我的场景中它并不是合适的解决方案:在可信环境中自动测试vanilla已安装的系统,其中不希望/可能向图像添加可信密钥。
答案 0 :(得分:7)
你可能想要:
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
}
eof
命令完成后,您点击foo
。
答案 1 :(得分:2)
好的,所以我发现了一种似乎有用的排列 -
首先,我需要一个wrapper
脚本,在完成后会给出指示:
#!/bin/bash
"$@"
echo "done"
然后期望脚本变为:
#!/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 }
}
感谢 Douglas Leeder (已投票)和 glenn jackman (已投票)以获得有用的建议。我很乐意不接受这个答案,并接受任何更优雅的答案,也许是一个废除包装脚本的答案。
谢谢大家的关注。
答案 2 :(得分:1)
这个循环:
expect {
"*yes/no*" { send "yes\r" ; exp_continue }
"*assword:" { send "${password}\r" ; exp_continue }
}
除超时或EOF外无法终止;两条匹配的行将exp_continue
,所以再次绕循环。
进入背景意味着基本上分叉;父母去世,孩子继续连接。
就个人而言,我会以不同的方式解决互动元素:
答案 3 :(得分:0)
我这样做的方式:
set user "****"
set host "127.0.0.1"
spawn shh $user@$host
expect "password: "
send "**??54"
expect "$"
interact
(回答你如何使用互动方法)