I am struggling with the classic problem of typing password automatically in ssh, and like everybody else I am stumbling in the dark regarding expect. Finally I cobbled together a script that kinda work:
#!/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 }
}
This script terminates only thanks to the timeout 1
line, without it it simply hangs, and will terminate only by user interaction (^C
).
When the spawn
line was a straight forward ssh command, the script terminated right away, however this is not your straight forward ssh. The thing that might be different is the -f
option that make it run in the background (but I tried the script without it to no avail).
I read that interact
or expect eof
might help, but I wasn't able to find the correct incantation that will actually do it.
My question (I think) is How to make an expect script, that spawn a background process, terminate without a timeout?
Edit: I should have expected (no pun intended) the "use passwordless ssh authentication" answer. While this is a sound advice, it is not the appropriate solution in my scenario: Automatic testing a vanilla installed system in a trusted environment, where adding trusted keys to the image is not desirable / possible.
You probably want:
expect {
"*yes/no*" { send "yes\r" ; exp_continue }
"*assword:" { send "${password}\r" }
}
expect $the_prompt
send "exit\r"
expect eof
UPDATE
I missed that you are sending a command via ssh. I think all you need is this:
spawn ssh a@b foo bar baz
expect {
"*yes/no*" { send "yes\r" ; exp_continue }
"*assword:" { send "${password}\r" }
eof
}
You'd hit eof
when the foo
command completes.