Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

expect and ssh-copy-id

31 views
Skip to first unread message

rambiuspa...@gmail.com

unread,
Dec 15, 2017, 4:12:54 PM12/15/17
to
Hello,

I am automating the transfer of a public ssh key to several hosts using expect. If the key is not in the remote authorized_keys file the following snippet works fine:

spawn ssh-copy-id $host
expect "password: "
send -- "$pass\n"
expect "$ "

However, if the key has already been added in authorized_keys ssh-copy-id reports so and does not prompt for password. How can I differentiate between these two cases? The exit codes of ssh-copy-id are the same for both of them. The output when the key is being added is

$ ssh-copy-id host1
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys

rambius@host1's password:

When the key is in authorized_keys the output is

$ ssh-copy-id host22
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed

/usr/bin/ssh-copy-id: WARNING: All keys were skipped because they already exist on the remote system.

How can I send the password in the first case and do nothing in the second?

Regards
rambius

Bezoar

unread,
Dec 17, 2017, 10:37:30 AM12/17/17
to
Problem that you are having is that you do run the send command as a consequence of first getting the password. So after the default timeout you send the password when no password prompt is seen and if you get a password you send the timeout. This is some boiler plate code I use to login to ssh and execute a command you can convert it to run your command just change the spawn invocation.

#!/bin/sh
# the next line restarts using wish \
exec /opt/usr8.6.3/bin/tclsh8.6 "$0" ${1+"$@"}

foreach pkg { Expect } {
if { [ catch {package require $pkg } err ] != 0 } {
puts stderr "Unable to find package $pkg\n$err\n ... adjust your auto_path!";
}
}
proc runSSHCommand { command user host password } {
set pid [ spawn ssh ${user}@${host} $command ]
set spawn_id $spawn_id;
set timeout 10
set bad 0;
set done 0;
exp_internal 0; # set to one for extensive debug
log_user 0; # set to one to watch action
set output ""
expect {
-i $spawn_id
-re {^.*password:} {
exp_send "$password\r"
}
-re {.*\(yes/no\)\?[ ]*$} {
# if a new host may need to agree to pass the host keys
exp_send "yes\r"
exp_continue; # stay inside this expect like a while loop without this we exit this expect
}
-re {Temporary failure in name resolution} {
# handle dns failure ... should use ip address or FQDN
append output $expect_out(buffer)
append output "$host was not found use IPAddress or FQDN for host\n"
set bad 1
}
timeout {
send_user "No password was sent\n"
}
fullbuffer {
# expect fill up after 10000 bytes 'fullbuffer' event hits at this point you can save the expect_out(buffer) here
# or ignore it
exp_continue;
}
eof {
set done 1 ;
}
}
if { !$done && !$bad} {
expect {
-i $spawn_id
-re {.{30}} {
# get every 30 characters change this as appropirate
send_user "."
append output $expect_out(buffer);
exp_continue; # stay inside this expect like a while loop without this we exit this expect
}
timeout {
send_user "hmm process is taking too long killing "
exec kill -9 $pid
set bad 1
}
fullbuffer {
# expect fill up after 10000 bytes 'fullbuffer' event hits at this point you can save the expect_out(buffer) here
# or ignore it
append output $expect_out(buffer)
exp_continue;
}
eof {
append output $expect_out(buffer)
send_user "\nall done!"
set done 1 ;
}
}
}
set exitstatus [ exp_wait -i $spawn_id ];
catch { exp_close -i $spawn_id };
if { $bad } {
throw ERROR $output
}
return $output
}
try {
set output [runSSHCommand {cat backup.tcl} username host password ]
} trap ERROR {a } {
puts "Error : $a"
exit 1
} on error { a b } {
puts "Unexpected error: $a \n$b"
exit 1
}
puts $output
puts "SUCCESS!"
exit 0

Bezoar

unread,
Dec 17, 2017, 10:39:36 AM12/17/17
to
first line should read : Problem that you are having is that you do NOT run the...

Andreas Leitgeb

unread,
Dec 17, 2017, 10:47:57 AM12/17/17
to
rambiuspa...@gmail.com <rambiuspa...@gmail.com> wrote:
> I am automating the transfer of a public ssh key to several hosts using
> expect. If the key is not in the remote authorized_keys file the following
> snippet works fine:
>
> spawn ssh-copy-id $host
> expect "password: "
> send -- "$pass\n"
> expect "$ "
>
> However, if the key has already been added in authorized_keys ssh-copy-id
> reports so and does not prompt for password. How can I differentiate
> between these two cases? The exit codes of ssh-copy-id are the same for
> both of them. The output when the key is being added is

I'd examine the "expect" command docs more closely: this command really
wants a list of patterns and bodies to run in case the patterns match.

For a starter use this, and then you can extend it by more patterns.

rambiuspa...@gmail.com

unread,
Dec 18, 2017, 10:22:13 AM12/18/17
to
Thank you all for your responses. I am working through them.

Regards
rambius
0 new messages