We’ve all been there, we have a bunch of linux boxes with user accounts set up and no SSH keys. If you are like most linux users out there you have probably read more than a few guides on setting up simplified access using SSH keys, but one thing that seems to be missing is a guide on how to efficiently deploy your SSH keys so that you don’t have to login to dozens or hundreds of machines. Enter the script below.
#!/usr/bin/perl
# Perl key deployer
# Usage: sshDeploy.pl serverlist
# I generally always use strict and warnings when developing scripts you can remove warnings to potentially get better performance
use strict;
use warnings;
# We will be using expect to manage the login process for copying the SSH keys
use Expect;
# Fancy password prompt
use Term::ReadKey;
print "Enter your password: ";
ReadMode('noecho');
my $password = ReadLine(0);
chomp $password;
ReadMode('normal');
open('FH', "./serverlist") or die "can't open ./serverlist: $!";
# Loop through the file of hostnames one at a time
while (defined (my $host = <FH>)) {
chomp $host;
# Check to see if key authentication is already working so we don't copy the key twice.
if(system("ssh -o BatchMode=yes -o ConnectTimeout=5 $host uptime 2>&1 | grep -q average") != "0")
{
# Set up the command to copy the ssh key
my $cmd = "ssh-copy-id -i $host";
# Print comfort text
print "Now copying key to $host";
# Set up expect and spawn a command
my $timeout = '10';
my $ex = Expect->spawn($cmd) or die "Cannot spawn $cmd\n";
# Look for the password prompt and send the password
$ex->expect($timeout, ["[pP]assword:"]);
$ex->send("$password\n");
$ex->soft_close();
} else { print "Key already deployed on $host\n" }
}
close('FH');
Super simple script. The most complicated section is the expect. This has saved me quite a bit of time and hopefully it will save you time as well.
UPDATE: Apparently there was an error in translation. I missed the filehandle in the while loop when copying the script over. I also added a timeout to the ssh command. The timeout is not the end all be all, you should probably add a host up check.