退出期望{}没有超时

时间:2010-06-29 13:58:22

标签: 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 $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选项使其在后台运行(但我尝试了没有它的脚本无效)。

我认为interactexpect eof可能有所帮助,但我无法找到真正实现此目的的正确咒语。

我的问题(我认为)是如何制作一个期望脚本,产生后台进程,终止而不会超时?


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

4 个答案:

答案 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,所以再次绕循环。

进入背景意味着基本上分叉;父母去世,孩子继续连接。

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

  1. 主机密钥:手动连接一次,或直接在ssh known_hosts文件中插入密钥。
  2. 密码:我使用私钥/公钥验证。使用代理存储密钥,或使用无密码密钥。

答案 3 :(得分:0)

我这样做的方式:

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

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