1#! /usr/bin/perl 2# 3 4# 5# sjobexitmod 6# 7# Author: Phil Eckert 8# Date: 10/28/2010 9# Last Modified: 10/28/2010 10# 11 12BEGIN { 13 # Just dump the man page in *roff format and exit if --roff specified. 14 foreach my $arg (@ARGV) { 15 if ($arg eq "--") { 16 last; 17 } elsif ($arg eq "--roff") { 18 use Pod::Man; 19 my $parser = Pod::Man->new (section => 1); 20 $parser->parse_from_file($0, \*STDOUT); 21 exit 0; 22 } 23 } 24} 25 26use strict; 27use Getopt::Long 2.24 qw(:config no_ignore_case); 28use autouse 'Pod::Usage' => qw(pod2usage); 29use File::Basename; 30 31my ( 32 $base, $help, $cluster, $code, $execute_line, 33 $jobid, $list, $man, $reason 34); 35 36# 37# Format for listing job. 38# 39my $list_format = "JobID,Account,NNodes,NodeList,State,ExitCode,DerivedExitCode,Comment"; 40 41 42# 43# Get options. 44# 45getoptions(); 46 47my $rval; 48 49# 50# Exexute the utility. 51# 52$rval = `$execute_line 2>&1`; 53 54# 55# Determine if Successful. 56# 57my $status = $?; 58 59if ($status == 0) { 60 printf("\n Modification of job $jobid was successful.\n\n"); 61 exit(0); 62} else { 63 printf("\n $rval\n"); 64 exit($status); 65} 66 67 68 69sub getoptions 70{ 71 my $argct = $#ARGV; 72 73# 74# Set default partition name. 75# 76 77 GetOptions( 78 'help|h|?' => \$help, 79 'man' => \$man, 80 'e=s' => \$code, 81 'r=s' => \$reason, 82 'c=s' => \$cluster, 83 'l' => \$list, 84 ) or usage(); 85 86# 87# Fix the exit code (if set) to reflect the 88# fact that it represents the leftmost 8 bits 89# of the integer field. 90# 91 $code = 256 * ($code & 0xFF) if ($code); 92 93# 94# 95# Display a simple help package. 96# 97 usage() if ($help); 98 99 show_man() if ($man); 100 101# 102# Make sure there is a job id, and make sure it is numeric. 103# 104 if (!($jobid = shift(@ARGV)) || !isnumber($jobid)) { 105 printf("\n Job Id needed.\n\n"); 106 usage(); 107 } 108 109# 110# List option was selected. 111# 112 if ($list) { 113 die(" \n wrong use of list option, format is ' $base -l JobId'\n\n") if ($argct != 1); 114 system(" sacct -X -j $jobid -o $list_format"); 115 exit(0); 116 } 117 118# 119# Check for required options. 120# 121 if (!$reason && !$code) { 122 printf("\n Either reason string or exit code required.\n\n"); 123 exit(1); 124 } 125 126# 127# Build execute line from the options that are set. 128# 129 $execute_line = "sacctmgr -i modify job jobid=$jobid set"; 130 131 $execute_line .= " Comment=\"$reason\"" if ($reason); 132 $execute_line .= " DerivedExitCode=$code" if ($code); 133 $execute_line .= " Cluster=$cluster" if ($cluster); 134 135 return; 136} 137 138 139# 140# Simple check to see if number is an integer, 141# retrun 0 if it is not, else return 1. 142# 143sub isnumber 144{ 145 my ($var) = $_; 146 147 if ($var !~ /\D+/) { 148 return(1); #if it is just a number. 149 } else { 150 return(0); #if it is not just a number. 151 } 152} 153 154 155sub usage 156{ 157 my $base = basename($0); 158 159 printf("\ 160 Usage: $base [-e <exit code>] [-r <reason string>] [-c <cluster>] JobId 161 $base -l JobId 162 $base [-h] 163 $base [-man] 164 165 -e <exit code> Modify the derived exit code to new value. 166 -r <reason string> Modify the job's comment field to new value. 167 -c <cluster> Name of cluster (optional). 168 -l List information for a completed job. 169 -h Show usage. 170 JobId The identification number of the job. 171 -man Show man page. 172 173\n"); 174 175 exit; 176} 177 178sub show_man 179{ 180 181 if ($< == 0) { # Cannot invoke perldoc as root 182 my $id = eval { getpwnam("nobody") }; 183 $id = eval { getpwnam("nouser") } unless defined $id; 184 $id = -2 unless defined $id; 185 $< = $id; 186 printf("\n You can not do this as root!\n\n"); 187 exit 1; 188 } 189 $> = $<; # Disengage setuid 190 $ENV{PATH} = "/bin:/usr/bin"; # Untaint PATH 191 delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'}; 192 if ($0 =~ /^([-\/\w\.]+)$/) { $0 = $1; } # Untaint $0 193 else { die "Illegal characters were found in \$0 ($0)\n"; } 194 pod2usage(-exitstatus => 0, -verbose => 2); 195 196 return; 197} 198 199__END__ 200 201 202=head1 NAME 203 204B<sjobexitmod> - Modifies a completed job in the slurmdbd 205 206=head1 SYNOPSIS 207 208 sjobexitmod [-e exit_code] [-r reason_string] [-c cluster_name] JobId 209 sjobexitmod -l JobId 210 sjobexitmod -h 211 sjobexitmod -man 212 213=head1 DESCRIPTION 214 215 sjobexitmod is a wrapper which effectively does the same operation as using the 216 sacct utility to modify certain aspects of a completed job. 217 218 sacctmgr -i modify job jobid=1286 set DerivedExitCode=1 Comment="code error" 219 220 or to list certain aspects of a completed job. 221 222 sacct -o jobid,derivedexitcode,comment,cluster 223 224=head1 OPTIONS 225 226=over 4 227 228=item B<-h> 229 230A usage summary message is displayed, and sjobexitmod terminates. 231 232=item B<-man> 233 234Show the man page for this utility.. 235 236=item B<-c> I<cluster_name> 237 238The name of the cluster the job ran on. 239 240=item B<-e> I<exit_code> 241 242The exit code (DerivedExitCode) to be used. 243 244=item B<-l> I<JobID> 245 246List selected attributes of a completed job. 247 248=item B<-r> I<reason_string> 249 250The reason (Comment) for job termination. 251 252=item B<JobId> 253 254the numeric job id. 255 256=back 257 258=head1 EXIT CONDITIONS 259 260If there is an error, sjobexitmod returns either the exit status returned by sacctmgr, 261or a non-zero value. 262 263=head1 AUTHOR 264 265Written by Philip D. Eckert 266 267=head1 REPORTING BUGS 268 269Report bugs to <pdesr@llnl.gov> 270 271=head1 SEE ALSO 272 273sacctmgr,sacct 274 275