退出期望{}没有超时

Che*_*evy 8 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 }
}
Run Code Online (Sandbox Code Playgroud)

此脚本仅timeout 1在线路上终止,没有它只是挂起,并且只能通过用户交互(^C)终止.

当该spawn行是一个直接的ssh命令时,脚本立即终止,但这不是你的直接ssh.可能不同的是-f使它在后台运行的选项(但我尝试了没有它的脚本无济于事).

我读过这个interact或者expect eof可能会有所帮助,但我找不到真正能做到的正确的咒语.

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


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

gle*_*man 7

你可能想要:

expect {
    "*yes/no*" { send "yes\r" ; exp_continue }
    "*assword:" { send "${password}\r" }
}
expect $the_prompt
send "exit\r"
expect eof
Run Code Online (Sandbox Code Playgroud)

UPDATE

我错过了你通过ssh发送命令.我想你需要的就是这个:

spawn ssh a@b foo bar baz
expect {
    "*yes/no*" { send "yes\r" ; exp_continue }
    "*assword:" { send "${password}\r" }
    eof
}
Run Code Online (Sandbox Code Playgroud)

你会打eof的时候foo命令完成.


Che*_*evy 2

好的,所以我找到了一个似乎有效的排列——

首先,我需要一个wrapper脚本,该脚本将在完成时给出指示:

#!/bin/bash
"$@"
echo "done"
Run Code Online (Sandbox Code Playgroud)

那么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 }
}
Run Code Online (Sandbox Code Playgroud)

感谢道格拉斯·利德( Douglas Leeder)(投票赞成)和格伦·杰克曼( glenn jackman)(投票赞成)提供的有用建议。我很乐意不接受这个答案,并接受任何更优雅的答案,也许是一个取消包装脚本的答案。

感谢大家的关注。