#!/usr/local/bin/perl # rjob: run a job on another machine on cluster in background. # Usage: # rjob [-h -host host] [-dir workdir] [-s -show] command # if no host specified, one with lowest load is selected (unless you # have submitted a job there in the last $waittime minutes). # if no working directory specified, work is done in current directory. # -s or -show will show the command to be run and prompt you whether to run it. # Caveats: # You must enclose command in double quotes if you have >, <, |, >>, & etc, # OR you can escape them with backslashes, \ # Examples: # rjob "a.out < input > output" (preferred) # rjob a.out \< input \> output # rjob "a.out \< input \> output" (not reco., for backward compat.) # rjob -host wren "a.out < input > output" # rjob -host wren -dir $HOME/work "hostname >>& file.out" # rjob "ps | grep a.out > file.out" # $waittime = '10'; # minutes waited to resubmit to same host $Nice = 'nice '; # we try to be... # Set following to your situation: # remote shell command #$RSH = 'rsh'; # BSD-ish $RSH = 'remsh'; # SVR4-ish $helpline = '37'; $waittime = $waittime/(24.0*60.0); # days! $machinedir = "$ENV{'HOME'}".'/bin/cluster/'; # location of recent usage data if ( ! -d $machinedir ) { system "mkdir $machinedir"; } LOOP: # process args while (@ARGV) { $_ = shift @ARGV; CASE: { /^-h$/ && ( $host = shift @ARGV, last CASE); /^-host$/ && ( $host = shift @ARGV, last CASE); /^-help$/ && ((system "head -$helpline $0"), exit 0, last CASE); /^-timefile$/ && ( (print "$machinedir $waittime\n"), exit 0, last CASE); /^-dir/ && ( $WD = shift @ARGV, last CASE); /^-s$/ && ( $show = 'True', last CASE); /^-show$/ && ( $show = 'True', last CASE); unshift(ARGV,$_); # put back if done with flags last LOOP; } } if ( $#ARGV == 0 ) { # if old form "a.out \< in \> out" $ARGV[0] =~ s/\\/>/g; $ARGV[0] =~ s/\\\|/\|/g; $ARGV[0] =~ s/\\&/&/g; $ARGV[0] =~ s/\\;/;/g; } unshift(ARGV,"$Nice"); # put nice onto command if( ! $WD) { $WD = $ENV{cwd};} # we come to present directory (default), if( ! $WD ) {chop($WD = `echo \$cwd`);} if( ! $WD ) {chop($WD = `pwd`);} if ($WD) { unshift(ARGV,"cd $WD",';'); # push cd cwd onto command } if ( ! $host ) { # try to grab least loaded... open(LIST,"ruptime | awk '{print \$1, \$7}' | sort -n +1 |"); while () { chop; ($host_try,$load) = split(' ',$_); next if $host_try =~ /swan/; # bad hosts, clean up next if $host_try =~ /thrush/; $machinefile = "$machinedir"."$host_try"; # # print "machinefile $machinefile\n"; # $wash = ( -M $machinefile ); # print "$wash $waittime \n"; # print "try $host_try..."; # check if old enough if(! -f $machinefile || -M $machinefile > $waittime) { $host = $host_try; print "OK\n"; last; } else { print "nope\n"; } } } if ( ! $host ) { # if still no host, select least loaded one I guess.. chop($host = `ruptime | awk '{print \$1, \$7}' | sort -n +1 | head -1`); $load = ''; ($host,$load) = split(' ',$host); } if ( ! $host ) { # if still no host, select present one! chop($host = `hostname`); } if(! $machinefile) { $machinefile = "$machinedir"."$host"; } push(ARGV,'&'); # push `&' to end of command # Debugging # print "\n"; foreach (@ARGV) { print; print "\n"; } print "\n"; # print "hostname $host\n"; print "\nWill run:\n"; $| = 1; $ErrorFile = "$ENV{'HOME'}/.errorWad"; # file to direct error... system "touch $ErrorFile"; # try to make exist if ( ! -f $ErrorFile ) { $ErrorFile = '/dev/null'; } print "$RSH $host -n \"( @ARGV ) >>& $ErrorFile \"\n"; if($show) { # show command and ask print "\nRun it? ([y]/n) "; chop($response = ); if ( $response ne 'y' && $response ne '' && $response ne 'Y' ) {print "Didn't run it\n"; exit 0;} else {print "OK, I run it\n";} } print "Errors and undirected output appended to $ErrorFile\n"; system "$RSH $host -n \"( @ARGV ) >>& $ErrorFile \" "; # run it if($machinefile) { system "rm -f $machinefile"; # update recent usage data system "touch $machinefile"; } print "\n"; system "(myjobs -nr $host; echo) &";