Reputation: 1325
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
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
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