TheCheatsrichter TheCheatsrichter - 2 months ago 24
Linux Question

Expect Script - Auto Password

I am trying to make a script which automatically enters the password "root" to copy the ssh-key from A to B. Since ssh-copy does not work on B and also cant be installed i used:

ssh root@$ip mkdir -p .ssh
cat "~/.ssh/id_rsa.pub" | ssh "root@$ip" 'cat >> .ssh/authorized_keys'


To transfer the key. But B delets its storage on reboot. So i have to automate this process. I thought a expect script would be the simplest solution? I am however not very experienced with these.

#!/usr/bin/expect
#31.09.2015

set timeout 30

spawn ssh "root@$ip mkdir -p .ssh"
expect "password:"
send "root\r"
expect "(yes/no)? "
send "yes\r"

spawn cat "~/.ssh/id_rsa.pub" | ssh "root@$ip" 'cat >> .ssh/authorized_keys'
expect "password:"
send "root\r"

interact


It seems to works till the first send. Then however gets stuck and waits for an input? (wrong expect?)

Answer

This is the part you're having trouble with:

spawn ssh "root@$ip mkdir -p .ssh"
expect "password:"
send "root\r"
expect "(yes/no)? "
send "yes\r"

After you send the password you're waiting 30 seconds for (yes/no? to appear, but it might not appear if you've connected to that machine before. You want to conditionally expect that y/n prompt:

spawn ssh "root@$ip mkdir -p .ssh"
expect {
    "(yes/no)? " { send "yes\r"; exp_continue }
    "password:"  { send "root\r" }
}
expect eof

That form of the expect command allows you to look for multiple strings simultaneously. If the first one seen is "(yes/no)? ", then send "yes" and continue with this expect command. When you see "password:", send the password and let the expect command end.

You might want to change the second spawn command so a shell can handle the pipeline.

set cmd [format {cat "~/.ssh/id_rsa.pub" | ssh "root@%s" 'cat >> .ssh/authorized_keys'} $ip]
spawn sh -c $cmd