8

我正在努力解决在 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 命令时,脚本会立即终止,但这不是您的直接 ssh。可能不同的是-f使它在后台运行的选项(但我尝试了没有它的脚本无济于事)。

我读过interact或者expect eof可能会有所帮助,但我无法找到真正能做到的正确咒语。

我的问题(我认为)是如何制作一个期望脚本,它产生一个后台进程,在没有超时的情况下终止?


编辑:我应该预料到(没有双关语)“使用无密码 ssh 身份验证”的答案。虽然这是一个合理的建议,但在我的场景中它不是合适的解决方案:在受信任的环境中自动测试 vanilla 安装的系统,在该环境中向图像添加受信任的密钥是不可取的/不可能的。

4

4 回答 4

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

于 2010-06-30T01:30:48.807 回答
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(投赞成票)提供的有用建议。我很乐意不接受这个答案,并接受任何更优雅的答案,也许是一个取消包装脚本的答案。

谢谢大家的关注。

于 2010-06-30T06:19:03.560 回答
1

这个循环:

expect {
    "*yes/no*" { send "yes\r" ; exp_continue }
    "*assword:" { send "${password}\r" ; exp_continue }
}

除了超时或 EOF 之外,不能以任何方式终止;两条匹配的线会exp_continue,所以再次循环。

进入后台基本上意味着分叉;父母死了,孩子继续连接。

就个人而言,我会以不同的方式解决交互元素:

  1. 主机密钥:手动连接一次,或直接将密钥插入 ssh known_hosts 文件中。
  2. 密码:我会使用私钥/公钥身份验证。要么使用代理来存储密钥,要么使用无密码密钥。
于 2010-06-29T14:07:19.777 回答
0

我这样做的方式:

set user "****"    
set host "127.0.0.1"    
spawn shh $user@$host    
expect "password: "    
send "**??54"    
expect "$"    
interact

(回答你如何使用交互方法)

于 2014-07-31T10:33:32.370 回答