barnett@grymoire.crd.ge.com (Bruce Barnett) (06/07/91)
Here is my first perl script. Be gentle - gang.
You can use this to execute "df -t 4.2" on hundreds of machines.
The script will spawn off several processes (default maximum: 6) and run an
rsh command in each. When each one terminates, a new rsh is executed.
So the rsh processes run in parallel. The name of the machine is
printed at the beginning of each line.
#!/usr/bin/perl # -*-Perl-*-
# This is a mux version of rsh
# it will do several rsh commands in parallel
# just the thing for doing "df -t 4.2" on 400 machines
#
# Bruce Barnett <barnett@crdgw1.ge.com>
# (Thanks to Randal for hard part)
#
# default number of processes is 6,
# but is resettable using the -m argument
#
# usage:
# muxrsh [-m max] [-v] [-l username] command [args ...] <list_of_machines
#
# example:
# muxrsh /bin/arch <machines
# muxrsh -m 10 /bin/arch <machines
# muxrsh -v -l staff df -t 4.2 <machines
#
# ------------------------------
# subroutine definitions ....
sub getswitches {
# parse arguments
while ($ARGV[0] =~ /^-/) {
$ARGV[0] =~ /^-v/ && ($verbose++,shift(@ARGV),next);
$ARGV[0] =~ /^-m/ && (shift(@ARGV),$maxpids = shift(@ARGV), next);
$ARGV[0] =~ /^-l/ && (shift(@ARGV),$remoteuser = "-l " . shift(@ARGV), next);
last;
}
}
sub wait {
$verbose && printf "process %d called wait with %d alive\n", $$, &alive;
local($somepid);
while ($somepid = wait) {
if (defined $pids{$somepid}) {
$verbose && print "wait saw $pids{$somepid}\n";
return delete $pids{$somepid};
} else {
$verbose && print "wait saw $somepid?\n";
}
}
warn "wait: nobody to wait on: $!";
}
sub alive {
local(@pids) = keys %pids;
return scalar(@pids);
}
# Main routine
sub doit {
while ($machine = <STDIN>) {
chop $machine;
$verbose && printf "forking for %s with %d alive\n", $machine, &alive;
&wait() if &alive > $maxpids;
$pid = fork;
die "fork: $!" unless defined $pid;
if ( $pid) { # parent
$pids{$pid} = $machine;
} else {
$results=`rsh -n $remoteuser $machine @ARGV 2>&1 `;
# this makes sure "machine: " is before each line returned.
@mresults = (split(/\n/, $results));
for $mresult (@mresults) {
print "$machine: $mresult\n";
}
exit 0;
}
}
&wait() while &alive > 0;
}
#--------------
# main routine
#
$|++; # flush buffers on a line-by-line basis
$verbose = 0; # assume verbose is off
$maxpids = 6; # default maximum number of processes
#$remoteuser="-l staff"; # default remote user
$remoteuser="";
%pids = (); # zero out the pids
&getswitches(); # get any switches/changes to defaults
@ARGV || die "Must specify a command to be executed!\n";
$verbose && $remoteuser && print "remote user is $remoteuser\n";
$verbose && print "Max number of processes is $maxpids\n";
&doit(); # tuit
0;
--
Bruce G. Barnett barnett@crdgw1.ge.com uunet!crdgw1!barnett