bluethundr
bluethundr

Reputation: 1325

Expect script fails if directory exists

My expect script that allows me to log into servers with my ssh key fails if the directory it tries to create is already there.

When I try to create the directory on the target server the whole script fails with this error:

    authorized_keys                                                                                                             100%  408   478.0KB/s   00:00
send: spawn id exp8 not open
    while executing
"send "$password\r""
    (procedure "check_host" line 5)
    invoked from within
"check_host $line"
    ("while" body line 2)
    invoked from within
"while {[gets $fp line] != -1} {
    check_host $line
}"
    (file "./transfer_keys.sh" line 29)

This is my script:

#!/usr/bin/expect

set timeout 20
set user my_user_name
set password my_pass
set auth_keys /home/my_user_name/.ssh/authorized_keys
set ssh_dir /home/my_user_name/.ssh

proc check_host {hostname} {
    global user password auth_keys ssh_dir
    spawn scp $auth_keys $user@$hostname:
    expect "password"
    send "$password\r"
    spawn ssh $user@$hostname
    expect "password"
    send "$password\r"
    expect "$ "                ;# adjust to suit the prompt accordingly
    send "mkdir $ssh_dir\r"
    send "chmod 700 .ssh\r"
    send "mv authorized_keys $ssh_dir\r"
    send "chmod 600 $ssh_dir/authorized_keys\r"
    send "exit\r"
    expect eof

}


set fp [open host.txt r]
while {[gets $fp line] != -1} {
    check_host $line
}
close $fp

If I delete the ~/.ssh directory on the target server and run it again it runs fine!

How can I create the ~/.ssh directory only on the target server if it doesn't exist?

Upvotes: 0

Views: 394

Answers (2)

rtx13
rtx13

Reputation: 2610

Per @glennjackman, you may benefit from using ssh-copy-id to copy public keys to another server.


You can use the following shell command list to determine whether or not you need to log in using a password:

ssh -o BatchMode=yes $host : || echo "host $host requires password login"

Upvotes: 1

meuh
meuh

Reputation: 12255

The scp will not ask for a password if you have already copied the authorization keys, and so expect "password" will timeout after 20 seconds. When the following send "$password\r" is done, the scp will have finished and the connection closed, hence the error.

Typically, expect is used not only to match a pattern, but then to also specify the command to run if it matches. Simply combine the expect and send in this way:

expect "password" { send "$password\r" }

Then the send will only be done if the prompt is seen. You should also add an expect eof for this scp command, to clean up the connection.

Upvotes: 1

Related Questions