#!/usr/bin/perl -w ########################################################################### # # qstat --> displays info about running/queued jobs # # Copyright 2008,2012 Philip Johnson. # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation, either version 3 of the License, # or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License at for # more details. # # Version history: # 1.0 --> Mar 2008 # 1.1 --> Aug 2008 Added query of condor_status to see if suspended # 1.2 --> Oct 2012 Report number CPUs requested if more than 1 # ########################################################################### use strict; my %machineStatus; x_GetMachineStatus(\%machineStatus); my $arg = join("' '", @ARGV); $arg = "'".$arg."'" if length($arg); open QPIPE, "condor_q -long $arg|" or die $!; #while (defined ($_ = ) && !/Submitter/) {} #print $_ if defined $_; my $colFormat = "%-8s %-10s%-4s%-15s%-10s%s\n"; printf $colFormat, 'ID', 'OWNER', 'ST', 'HOST', 'RUNTIME', 'CMD'; my %s; $s{host} = '--'; while () { if (/^$/) { if (defined($machineStatus{$s{host}}) && $machineStatus{$s{host}} eq 'Suspended') { $s{status} = 'S'; } my $runtime = '--'; if ($s{status} =~ 'I|H|X|C' && defined $s{currStart}) { $runtime = StringifyElapsedTime($s{RemoteWallClock} - $s{suspendTime}); } elsif ($s{status} =~ 'R|S') { if (exists($s{NumJobStarts}) && $s{NumJobStarts} > 1) { #can't use suspend time! $runtime = StringifyElapsedTime($s{currTime}-$s{currStart}); } else { $runtime = StringifyElapsedTime($s{currTime}-$s{currStart}- $s{suspendTime}); } $runtime = '<'.$runtime if ($s{status} eq 'S') } ($s{host}) = $s{host} =~ /(.+?)(?:\.|$)/; if ($s{cpus} > 1) { $s{host} = $s{cpus}.'*'.$s{host}; } if ($s{priority} != 0) { $s{status} .= sprintf '%+d', $s{priority}; } printf $colFormat, join('.', $s{clusterId}, $s{procId}), $s{owner}, $s{status}, substr($s{host},0,13), $runtime, $s{cmd}; undef %s; $s{host} = '--'; } if (/^ClusterId/) { ($s{clusterId}) = /(\d+)/; } elsif (/^ProcId/) { ($s{procId}) = /(\d+)/; } elsif (/^Owner/) { ($s{owner}) = /"(\S+)"/; } elsif (/^JobStatus/) { ($s{status}) = /(\d+)/; $s{status} = ('?', 'I', 'R', 'X', 'C', 'H', 'T', 'S')[$s{status}]; } elsif (/^RemoteHost/) { ($s{host}) = /"(\S+)"/; } elsif (/^CumulativeSuspensionTime/) { ($s{suspendTime}) = /(\d+)/; } elsif (/^LastSuspensionTime/) { ($s{lastSuspendTime}) = /(\d+)/; } elsif (/^JobCurrentStartDate/) { ($s{currStart}) = /(\d+)/; } elsif (/^ServerTime/) { ($s{currTime}) = /(\d+)/; } elsif (/^RemoteWallClock/) { ($s{RemoteWallClock}) = /(\d+)/; } elsif (/^Env =/) { ($s{cmd}) = /CONDOR_CMD_LINE=(.+?);/; $s{cmd} =~ s/SeMiCoLoN/;/g; $s{cmd} =~ s/\\"/"/g; #condor escapes quotes in Env on output } elsif (/^NumJobStarts/) { ($s{NumJobStarts}) = /(\d+)/; } elsif (/^JobPrio/) { ($s{priority}) = /(-?\d+)/; } elsif (/^RequestCpus/) { ($s{cpus}) = /(\d+)/; } } close QPIPE; # ------------------------------------------------------------------------- # Take an elapsed time in seconds and make meaningful string # sub StringifyElapsedTime { my ($t) = @_; my $s = ''; if (int($t / (24*3600))) { $s .= int($t / (24*3600)). 'd:'; $s .= int(($t % (24*3600))/3600). 'h'; } elsif (int(($t % (24*3600))/3600)) { $s .= int(($t % (24*3600))/3600). 'h:'; $s .= int(($t % 3600)/60). 'm'; } elsif (int(($t % 3600)/60)) { $s .= int(($t % 3600)/60). 'm:'; $s .= ($t % 60). 's'; } else { $s .= $t.'s'; } return $s; } # ------------------------------------------------------------------------- # Get machine status (importantly, this says whether suspended or not) # sub x_GetMachineStatus { my ($machStat) = @_; open(PIPE, "condor_status -format '%s\t' Name -format '%s\n' Activity|"); while () { chomp; my ($mach, $activity) = split; $machStat->{$mach} = $activity if (defined($mach)); } close(PIPE); }