#!/home/p/perl5 -w use FindBin qw($Bin); use strict; use lib ("$ENV{HOME}/cvs/triskman/pm", "$Bin/../pm", "/home/t/triskman/share/lib", "/home/p/triskman/share/lib"); use Data::Dumper; use POSIX; use Arguments; my $processfile = "/tmp/process.in"; my $donefiles = ""; my $rootlogdir = "/home/nk00637/tmp7/logs"; my $daemon = 0; my $LDLP="/home/p/triskman/sparc-sunos5/lib"; my $MACS = "/tmp/usable.lst"; my $parse_ref = [ [ "in" => \$processfile, {USAGE => 'input file for list of cmd files'} ], [ "done" => \$donefiles, {USAGE => 'outfile file for list of completed cmd files'} ], [ "logdir" => \$rootlogdir, {USAGE => 'log dir'} ], [ "dmn|d|daemon" => \$daemon, { TYPE => argTypeSwitch(), USAGE => "run as daemon" } ], [ "machine|m" => \$MACS, { USAGE => "machine list" } ], ]; Arguments::parse(@ARGV, $parse_ref); unless ($donefiles) { $donefiles = "$processfile.done"; } system("mkdir -p $rootlogdir") unless -d $rootlogdir; if ($daemon) { daemonify(); open (LOG, "> $rootlogdir/daemon.log") || die "can't open log in ($rootlogdir)\n"; } else { *LOG=*STDOUT; } my %machines; my %log_files = (); update_mac_list(\%machines); while (1) { my @files = get_file_list($processfile, $donefiles); exit 0 if $#files < 0; foreach my $file (@files) { print LOG "Processing file : $file\n"; # Process file # 1. read commands in the file my @commands = get_list($file); my $i = 0; foreach my $cmd (@commands) { # 2.1 wait till machines are free my $mac = get_free_mac(\%machines, \%log_files); $i++; print LOG "doing command ($mac): $cmd\n"; my ($err, $std) = log_files($rootlogdir, $file, $mac, $i); # 2.2 run the command on free machine system "echo 'CMD : $cmd' > $std"; # system "rsh $mac 'echo Begin ...; ; export DA=/home/t; export SYBASE=/home/t/sybase; export LD_LIBRARY_PATH=$LDLP; $cmd; echo End ...;'>>$std 2>$err &"; system "ssh -q $mac 'echo Begin ...; date ; export AUTOSERV=TDA; export DA=/home/p; export SYBASE=/home/p/sybase; export LD_LIBRARY_PATH=$LDLP; . /home/p/tkautosys/env/auto.profile; $cmd; echo EXITSTAT = \$\?; date ; echo End ...; '>>$std 2>$err &"; $log_files{$mac} = $std; unless ($i % 60) { print LOG "sleeping for 20 secs (30 jobs already running)\n"; sleep 20; } } # done system "printf '$file\n' >> $donefiles"; } } close LOG if $daemon; exit 0; sub getmaclist { return map { chomp; ($_, 1) } grep { s/\#.*//; !/^\s*$/ } `cat $MACS`; } sub update_mac_list { my ($mlist) = @_; my %nlist = getmaclist(); my $updated = 0; foreach my $mac (keys %$mlist) { unless (exists $nlist{$mac}) { delete $mlist->{$mac}; $updated = 1; } } foreach my $mac (keys %nlist) { unless (exists $mlist->{$mac}) { $mlist->{$mac} = 1; $updated = 1; } } if ($updated) { print LOG "USING UPDATED MAC LIST : ", join ", ", keys %$mlist; print LOG "\n"; } } sub get_free_mac { my ($mac_list, $logs) = @_; update_mac_list($mac_list); my $macname = (grep { $mac_list->{$_} } keys %$mac_list)[0]; unless ($macname) { my @macs = (); while (!scalar(@macs)) { while (my ($mac, $log) = each %$logs) { update_mac_list($mac_list); my $last = `tail -1 $log`; if ($last && $last =~ /End/) { push @macs, $mac if exists $mac_list->{$mac}; delete $logs->{$mac}; } } unless (scalar(@macs)) { print LOG "Machines not available ... sleeping for 30 secs\n"; sleep 30; } } foreach my $mac (@macs) { $macname = $mac; $mac_list->{$macname} = 1; } } while (1) { my @rsh = `ps -ef | grep ssh | grep Beg`; if (scalar(@rsh) <= ($ENV{MAX_PORT} || 300)) { last; } else { print LOG "300 ports in use ...\n"; sleep 10; } } $mac_list->{$macname} = 0; return $macname; } sub get_file_list { my ($in, $out) = @_; my %in = map { $_, 1} get_list($in); my %out = map { $_, 1} get_list($out); return (grep { !exists $out{$_} } keys %in); } sub get_list { my $file = shift; my @data = -f $file ? grep { !/^\s*$/ && !/^\#/ } `cat $file` : (); chomp @data; return @data; } sub log_files { my ($root, $dir, $mac, $index) = @_; my $base = `basename $dir`; chomp $base; my $log = "$root/$base"; system "mkdir -p $log" unless -d $log; $log .= "/out.$index.$mac"; return ("$log.err", "$log.std"); } sub daemonify { my $pid; if ($pid = fork) { # parent: exit exit 0; } # If we are here, it must be child or we had an error in fork die "Can't fork new process: $!" if $pid < 0; # Let's make the child the session leader, so to detach # from the control tty my $sess_id = POSIX::setsid(); # log_msg($Info, "Started daemon, session id: $sess_id ."); return $sess_id; }