Here is a small and convenient tool to execute same command over a set of Linux machines.
To use the tool we need to configure the machines for password-less SSH, also need Perl module Net::OpenSSH. We have to create a file $HOME/.allhosts and put the IP addresses or host names in this file in separate lines.
Configuring password-less access to all the machines you have
generate punblic and private keys
$ssh-keygen -t rsa -P '' -f ~/.ssh/id_rsa
$ssh-keygen -t rsa -P '' -f ~/.ssh/id_rsa
copy the public and private keys to all the machines you want to passwordless access:
scp ~/.ssh/id_rsa.pub userid@machine-ip:~/.ssh/id_rsa.pub
scp ~/.ssh/id_rsa userid@machine-ip:~/.ssh/id_rsa
scp ~/.ssh/id_rsa userid@machine-ip:~/.ssh/id_rsa
Add the public key to the authorized keys files on every machines:
cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
Now you will be able to ssh from any of these machines to any of these machines without a password
Install perl Net::OpenSSH module as shown below:
$sudo yum install perl-CPAN
$sudo perl -MCPAN -e "install Net::OpenSSH"
Examples
to kill all the java processes running in the machines listed in yout $HOME/.allhosts, issue the below command:
$ perl multihostcmd.pl "ps -ef | grep java | grep -v grep | awk ' { print \$2 }' | xargs kill -9"
Of course you will need permission to kill those processs
To check all the users logged to these machines, issue the below command
$ perl multihostcmd.pl who
$ perl multihostcmd.pl who
Below is the script (you may also access it in github ):
#!/usr/bin/perl ############################################################################ # Save this in a a file, say multihostcmd.pl ############################################################################ use threads ( 'yield', 'stack_size' => 64 * 4096, 'exit' => 'threads_only', 'stringify' ); use Cwd qw(abs_path); use Net::OpenSSH; # # executeCmdRemote # executes the command on a remote host # command execution happens over ssh # sub executeCmdRemote { my ( $host, $command, @others ) = @_; my $ssh = Net::OpenSSH->new($host, master_opts => [-o => "ConnectionAttempts=2", -o => "ConnectTimeout=5"] ); if ($ssh->error) { return; } ($out, $err, @others) = $ssh->capture2({timeout => 20}, $command); $outdata = "FROM $host ******************************************\n"; if ($out ne "") { $outdata .= $out; } if ($err ne "") { $outdata .= $err; } $outdata .= "\nEND OF DATA FROM $host ************************************* \n\n"; print $outdata; } # # readHostFile # reads from the file $HOME/.allhosts where this file contain a list of hosts # each line on this file denotes a host name or host ip # The given command is executed on this host # sub readHostFile { my ($array, @others) = @_; $hostfile = $ENV{'HOME'} . '/.allhosts'; if (! -e $hostfile) { print $hostfile . ' doesn\'t exist'; return; } if (! -f $hostfile) { print $hostfile . ' is not a regular file'; return; } open FH, "< $hostfile" || return; @$array = <FH>; close FH; } sub main { if ( $#ARGV < 0 ) { $executing_script = abs_path($0); print "Usage: $executing_script command-to-execute\n"; exit(1); } $cmdline = join( ' ', @ARGV ); my @hostarry = (); readHostFile(\@hostarry); if ($#hostarry < 0) { print "Empty list for hosts"; exit(1); } my $thr = undef; my @allthreads = (); foreach my $host (@hostarry) { $host =~ s/^\s+//; $host =~ s/\s+$//; if ($host eq "") { next; } # Create a thread to execute the command on the remote host $thr = threads->create('executeCmdRemote', $host, $cmdline); push @allthreads, $thr; } foreach $thr (@allthreads){ $thr->join(); } } # Call main main();
No comments:
Post a Comment