|
Home | Switchboard | Unix Administration | Red Hat | TCP/IP Networks | Neoliberalism | Toxic Managers |
(slightly skeptical) Educational society promoting "Back to basics" movement against IT overcomplexity and bastardization of classic Unix |
|
The qh
program parses the SGE information similar to qb
, but shows different
kinds of per-machine data. This can include the machine's architecture, the maximum amount of memory,
etc.
jbp@head1 [ 84 ] % qh
as of Fri Feb 2 10:57:06
2007
05:08
| lx26-amd64 | lx26-amd64 | lx26-amd64 | lx26-amd64 |
005:008
| lx26-x86 | lx26-x86 | lx26-x86 | lx26-x86
|
013:016
| lx26-x86 | lx26-x86 | lx26-x86 | lx26-x86
|
05:08
| lx26-amd64 | lx26-amd64 | lx26-amd64 | lx26-amd64 |
chg 01:04
| lx26-x86 | lx26-x86 | lx26-x86 | lx26-x86
|
compbio 01:04 | lx26-amd64
| lx26-amd64 | lx26-amd64 | lx26-amd64 |
compeb 01:04 |
lx26-x86 | down | lx26-x86 | lx26-x86
|
|
Use "qh -h
" to show a list of possible data-items that can be shown.
The output can be useful, especially in conjunction with qb
, to understand why a given
job might not be capable of running yet. While qb
may show open nodes, qh
may show that those nodes are all 32-bit and hence a 64-bit job will have to wait.
Some other options:
?qh -d mem_total |
Shows the total amount of memory on the machines
?qh -m -d mem_total |
will show the values in MB (default is GB)
?qh -d mhz |
shows the MHz (or GHz) rating of the machines, i.e. which machines are faster than other.
?qh -C 4 |
if the output from qh
looks too cramped, you can specify the number of columns you want
in the output (default is to make a guess at what will fit in an 80-column screen).
#!/usr/bin/perl # # (C) 2004-2009, John Pormann, Duke University # [email protected] # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. # # RCSID $Id: qh,v 1.11 2007/01/02 15:55:39 jbp1 Exp jbp1 $ # # qh - produce a 'block' view of some cluster/queue data item use Getopt::Std; getopts('hvVxC:d:m'); if( defined($opt_h) ) { print "usage: qh [opts]\n" . " -d data data-item to show (see below)\n" . " -m convert memory values to MB (default=GB)\n" . " -C cols use alternate number of columns in output\n" . " -v verbose\n" . " -V really verbose\n"; print "\navailable data-items:\n" . " arch num_proc mem_total swap_total virtual_total load_avg\n" . " load_short load_medium load_long mem_free swap_free virtual_free\n" . " mem_used swap_used virtual_used cpu mhz scr_free np_load_avg\n" . " np_load_short np_load_medium np_load_long\n"; exit; } if( defined($opt_V) ) { $opt_v = $opt_V; } if( not defined($opt_d) ) { $opt_d = 'mem_free'; } if( $opt_d eq 'arch' ) { $fmt = ' %10s '; } else { if( $opt_d =~ m/(mem|swap|virtual|scr)_/ ) { if( defined($opt_m) ) { $fmt = ' %.1fM '; } else { $fmt = ' %.1fG '; } } else { $fmt = ' %.1f '; } } %hinfo = (); $nextsym = 0; %subclusters = (); $hname = 'none'; $htext = ''; open( FP, "qhost -F |" ); # skip first two lines; ; while( ) { chomp( $_ ); $orig = $_; @fld = split( m/\s+/, $orig ); if( $fld[0] ne '' ) { # save last data if( ($hname ne 'global') and ($hname ne 'none') ) { $hinfo{$hname} = $htext; if( defined($opt_V) ) { print "storing host [$hname]\n"; } } $htext = ''; # new host entry $hname = $fld[0]; # is host down? # : for SGE6, fields 3 and 5 should say '-' if( $fld[3] =~ m/\-/ ) { $htext = 'down:'; if( defined($opt_V) ) { print "** host [$hname] is down\n"; } } # add to the 'subclusters' list $cluster = $fld[0]; $cluster =~ s/(.*?)\-(.*)/$1/; $subclusters{$cluster} = 1; } else { # this line goes with previous data $x = $fld[1]; $x =~ s/(..)\:(.*)/$2/; $htext .= $x . ':'; } } # don't forget the last line! if( ($hname ne 'global') and ($hname ne 'none') ) { $hinfo{$hname} = $htext; } close( FP ); if( defined($opt_v) ) { print "hinfo:\n"; foreach $key ( keys(%hinfo) ) { $val = $hinfo{$key}; print " [$key] [$val]\n"; } } @hostlist = sorthosts( keys(%hinfo) ); # # # # # # # # # # # # print header info # # # # # # # # # # # # $z = localtime; print "Cluster Information (by sub-cluster)\nas of $z\n\n" . " showing $opt_d\n\n"; # kludge up a better ordering for subclusters delete( $subclusters{'global'} ); @subclusterlist = sort(keys(%subclusters)); # try to pretty up the output # : find max jobs per machine $maxlen = 0; foreach $h ( keys(%hinfo) ) { $hi = $hinfo{$h}; if( $hi =~ m/down/ ) { $hi = 'down'; } elsif( $hi =~ m/\:$opt_d\=/ ) { $hi =~ s/(.*?)\:$opt_d\=(.*?)\:(.*)/$2/g; } else { $hi = 'unk'; } # convert memory values (if appropriate) if( $opt_d =~ m/(mem|swap|virtual|scr)_/ ) { if( defined($opt_m) ) { # show as MB if( $hi =~ m/G/ ) { $hi = ($hi+0)*1024; } } else { # show as GB if( $hi =~ m/M/ ) { $hi = ($hi+0)/1024; } } } # convert values to given format $hi = sprintf( $fmt, $hi ); # find length of data-item $n = length($hi); if( $n > $maxlen ) { $maxlen = $n; } } # : figure 80 cols - 6/3/3/4 = 64 chars in line $cols = int( 64/($maxlen+1) ); if( defined($opt_C) ) { $cols = $opt_C; } $n = -1; $f = 0; foreach $cluster ( @subclusterlist ) { $clst = $cluster; $strt = -1; $fnsh = -1; $text = ''; $n = 0; foreach $h ( @hostlist ) { if( $h !~ m/^$cluster/ ) { next; } if( $n == $cols ) { printf( "%-7s %3s:%-3s |%s\n", $clst, $strt, $fnsh, $text ); $clst = ''; $strt = -1; $fnsh = -1; $text = ''; $n = 0; } if( $strt < 0 ) { $strt = $h; $strt =~ s/(.*?)\-//g; $strt =~ s/\D//g; } $fnsh = $h; $fnsh =~ s/(.*?)\-//g; $fnsh =~ s/\D//g; $w = ''; $hi = $hinfo{$h}; if( $hi =~ m/down/ ) { $hi = 'down'; } elsif( $hi=~ m/\:$opt_d\=/ ) { $hi =~ s/(.*?)\:$opt_d\=(.*?)\:(.*)/$2/g; } else { $hi = 'unk'; } # convert memory values (if appropriate) if( $opt_d =~ m/(mem|swap|virtual|scr)_/ ) { if( defined($opt_m) ) { # show as MB if( $hi =~ m/G/ ) { $hi = ($hi+0)*1024; } } else { # show as GB if( $hi =~ m/M/ ) { $hi = ($hi+0)/1024; } } } # convert values to given format $hi = sprintf( $fmt, $hi ); $l = length($hi); if( $l < $maxlen ) { $text .= ' ' x ($maxlen-$l); } $text .= $hi . '|'; $n++; } printf( "%-7s %3s:%-3s |%s\n", $clst, $strt, $fnsh, $text ); print "\n"; } if( defined($opt_x) ) { exit; } # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # sorthosts subroutine by Benny Kjellgren <@staff.spray.se> # correctly sorts FQDN as well as non-FQDN sub sorthosts { my @unsorted = @_; my $fqdn; my $host; my $domain; my %domain; my %caps; my %nums; for( @unsorted ) { $fqdn = $_; ( $host, $domain ) = split('\.', $fqdn, 2); $domain{$fqdn} = uc($domain) || ""; ( $caps{$fqdn} = uc($host) ) =~ s/\d*$//; ( $nums{$fqdn} ) = ( $host =~ /(\d*)$/ ); $nums{$fqdn} = 0 unless $nums{$fqdn}; } my @list = sort { $domain{$a} cmp $domain{$b} || $caps{$a} cmp $caps{$b} || $nums{$a} <=> $nums{$b} } @unsorted; return( @list ); } sub get_header_info { my $aref = shift( @_ ); my $i = shift( @_ ); my ($y,$z,$cluster,$j,$jj); $cluster = $aref->[$i]; $cluster =~ s/(.*?)[\-\d](.*)/$1/g; # first node number for this cluster $y = $aref->[$i]; $y =~ s/\D+//g; # last node ( scalar(@$aref) ) { $z = $aref->[scalar(@$aref)-1]; last; } elsif( $aref->[$jj] !~ m/^$cluster/ ) { $z = $aref->[$jj-1]; last; } else { } } if( $z eq '' ) { $z = $aref->[$jj]; } $z =~ s/\D+//g; # trim cluster to only 6 letters $cluster =~ s/(......)(.*)/$1/; return( ($cluster,$y,$z) ); }