Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things
 
PerlMonks  

rcmd.pl

by greenFox (Vicar)
on Jul 25, 2002 at 12:26 UTC ( [id://185177]=sourcecode: print w/replies, xml ) Need Help??
Category: Utility Scripts
Author/Contact Info Murray Barton <muzza at iinet dot net dot au>
Description: rcmd.pl -a utility for running the same command across a group of hosts.
#!/usr/bin/perl -w
# 
# rcmd.pl
#
# run a command on multiple hosts!
# reads hosts from ~/rhosts
#
# if ~/rhosts is
#   host  group1,group3
#   host2  group2,group3
#   host3  group2
# then 
#  rcmd.pl -g group2 ls
# will run ls on host2 and host3
#
# great for run this command on "print hosts" or "solaris 8" machines 
+or
# red hat machines etc.
#
# Requires ssh installed- yeah I could have used Net:SSH, 
# not sure if that would any value though :)
#
# rcmd.pl started out as a quick and dirty one off 
# shell script and has grown...
#

use strict;
use Sys::Hostname;
use Getopt::Std;
my $home=get_home();
my %settings = (
          domain       => 'some.net.au',
          DEBUG        => 0,
          SSH          => "/usr/local/bin/ssh",
          SCP          => "/usr/local/bin/scp",
          HOST_FILE    => "$home/rhosts",
          runlocally   => 0,
        );

main_loop();
exit;

sub main_loop {

  my %args;
  getopts("g:hlnz", \%args);  # see print_help() for a description of 
+options
  print_help() and exit if $args{h};
  print_help() and exit if ! $args{g};
  my $host_group = $args{g} || '';
  my $no_prompt  = 1 if $args{n};
  my $no_errors  = 1 if $args{z};
  $settings{runlocally} = 1 if $args{l};
  print_help() and die "Specify command to run!\n" if ( ! scalar @ARGV
+);

  # the shell expands ~ and $home might be someplace different
  # on the destination host...
  my @command = map { s/^$home/~/; $_ } @ARGV;
  unshift @command, $settings{SSH};
  push @command, " 2>/dev/null" if $no_errors; 

  my @dest_hosts=get_hosts($settings{HOST_FILE}, $host_group);
  for my $host (@dest_hosts){
    unless ( $no_prompt ){
      print "Run @ARGV on $host [y/n]: ";
      chomp (my $answer = <STDIN>);
      next if ( $answer !~ /^y/i );
    }
    my @cmd = @command;
    splice(@cmd, 1, 0, $host);  # insert the hostname
    if ( $settings{runlocally} and $host eq $settings{localhost}){
      shift @cmd; shift @cmd;  # remove ssh and $hostname
    }
    print "Running [@cmd]\n" if $settings{DEBUG};
    my @result = `@cmd`;
    print "$host: ", @result, "\n";
  }
}

sub get_hosts {
  my $hosts_file = shift || die "sub get_hosts did not get a required 
+argument\n";
  my $host_group = shift || die "sub get_hosts did not get a required 
+argument\n";
  my $localhost = hostname();
  $localhost = (gethostbyname("$localhost.$settings{domain}"))[0] || $
+localhost;
  print "localhost: [$localhost]\n" if $settings{DEBUG};
  $settings{localhost} = $localhost;
  my @hosts;
  open (HOSTS, $hosts_file) || die "Could not open $hosts_file : $!\n"
+;
  while (<HOSTS>){
    next if /^\s*$/;
    next if /^\s*#/;
    chomp;
    my ($host, $groups) = split /\s+/;
    $host .= ".$settings{domain}" if ($host !~ /\./);
    my %groups = map { $_, 1 } split /,/, $groups;
    next if ( $host eq $localhost and ! $settings{runlocally});
    next if ( ! $groups{$host_group} and $host_group ne "all");
    print "Selecting [$host]\n" if $settings{DEBUG};
    push @hosts, $host;
  }  
  close(HOSTS);
  return @hosts;
}

sub get_home {
  my @pwd = getpwuid($<);
  my $home = $ENV{HOME} || $ENV{LOGDIR} || $pwd[7]
    or die "Could not determine home directory for $<";
  return $home;
}

sub print_help {
  print  "rput.pl -g <group> [options] file\n\n",
      "\twhere <group> is a group in your ~/rhosts file or \"all\"\n",
      "\t-h print this message\n",
      "\t-l run on local host\n",
      "\t-n no prompt just do it!\n",
      "\t-z suppres error messages\n";
}

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: sourcecode [id://185177]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others surveying the Monastery: (7)
As of 2024-03-28 19:04 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found