Last active
July 30, 2025 17:04
-
-
Save NQevxvEtg/dc3f08c773c06d4d690c99b544f68bea to your computer and use it in GitHub Desktop.
sshcopyid
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env expect -f | |
| # Prompt for SSH password once | |
| stty -echo | |
| send_user "Enter SSH password: " | |
| expect_user -re "(.*)\n" | |
| stty echo | |
| send_user "\n" | |
| set ssh_password $expect_out(1,string) | |
| set timeout 15 | |
| set hostfile [lindex $argv 0] | |
| set username [lindex $argv 1] | |
| set keyfile [file normalize "~/.ssh/id_rsa.pub"] | |
| set key [exec cat $keyfile] | |
| set key [string trim $key] | |
| # Escape double quotes etc. | |
| set key [string map {\a \\a \b \\b \\n \\\n \" \\\"} $key] | |
| set ok 0 | |
| set bad 0 | |
| set total 0 | |
| # For summary | |
| array set success {} | |
| array set failure {} | |
| set fh [open $hostfile r] | |
| while {[gets $fh line] >= 0} { | |
| set host [string trim $line] | |
| if {$host eq ""} continue | |
| incr total | |
| set target [expr {[regexp {@} $host] ? $host : "$username@$host"}] | |
| send_user "\n>>> Processing $target\n" | |
| # Step 0: Check if key already exists | |
| spawn ssh -o ConnectTimeout=8 -o StrictHostKeyChecking=accept-new \ | |
| $target "grep -Fxq \"$key\" ~/.ssh/authorized_keys" | |
| expect { | |
| -re "assword:" { | |
| send "$ssh_password\r" | |
| exp_continue | |
| } | |
| timeout { | |
| send_user "✗ $target timeout during key check\n" | |
| incr bad | |
| set failure($target) "timeout during key check" | |
| continue | |
| } | |
| eof { | |
| set exit_status [lindex [wait] 3] | |
| if {$exit_status == 0} { | |
| send_user "✓ $target already has key — skipping\n" | |
| incr ok | |
| set success($target) "already authorized" | |
| continue | |
| } | |
| } | |
| } | |
| # Step 1: Ensure ~/.ssh exists | |
| spawn ssh -o ConnectTimeout=8 -o StrictHostKeyChecking=accept-new \ | |
| $target "mkdir -p ~/.ssh && chmod 700 ~/.ssh" | |
| expect { | |
| -re "assword:" { | |
| send "$ssh_password\r" | |
| exp_continue | |
| } | |
| timeout { | |
| send_user "✗ $target timeout during mkdir\n" | |
| incr bad | |
| set failure($target) "timeout during mkdir" | |
| continue | |
| } | |
| eof {} | |
| } | |
| # Step 2: Copy key | |
| spawn scp -o ConnectTimeout=8 ~/.ssh/id_rsa.pub $target:/tmp/mykey.pub | |
| expect { | |
| -re "assword:" { | |
| send "$ssh_password\r" | |
| exp_continue | |
| } | |
| timeout { | |
| send_user "✗ $target timeout during SCP\n" | |
| incr bad | |
| set failure($target) "timeout during SCP" | |
| continue | |
| } | |
| eof {} | |
| } | |
| # Step 3: Append key | |
| spawn ssh -o ConnectTimeout=8 $target \ | |
| "cat /tmp/mykey.pub >> ~/.ssh/authorized_keys && \ | |
| chmod 600 ~/.ssh/authorized_keys && rm /tmp/mykey.pub" | |
| expect { | |
| -re "assword:" { | |
| send "$ssh_password\r" | |
| exp_continue | |
| } | |
| timeout { | |
| send_user "✗ $target timeout during key install\n" | |
| incr bad | |
| set failure($target) "timeout during key install" | |
| continue | |
| } | |
| eof { | |
| send_user "✓ $target key installed\n" | |
| incr ok | |
| set success($target) "key installed" | |
| } | |
| } | |
| } | |
| close $fh | |
| # Final Summary | |
| send_user "\n========== SUMMARY ==========\n" | |
| send_user "✅ Success : $ok\n" | |
| foreach host [array names success] { | |
| send_user " - $host : $success($host)\n" | |
| } | |
| send_user "\n❌ Failed : $bad\n" | |
| foreach host [array names failure] { | |
| send_user " - $host : $failure($host)\n" | |
| } | |
| send_user "\n📋 Total : $total\n" | |
| send_user "=============================\n" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment