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