| #! /usr/bin/perl -w |
| ############################################################################### |
| # |
| # qalter - PBS wrapper for changing job status using scontrol |
| # |
| ############################################################################### |
| |
| use strict; |
| use FindBin; |
| use Getopt::Long 2.24 qw(:config no_ignore_case); |
| use lib "${FindBin::Bin}/../lib/perl"; |
| use autouse 'Pod::Usage' => qw(pod2usage); |
| use Slurm ':all'; |
| use Slurmdb ':all'; # needed for getting the correct cluster dims |
| |
| # ------------------------------------------------------------------ |
| # This makes the assumption job_id will always be the last argument |
| # ------------------------------------------------------------------- |
| my $job_id = $ARGV[$#ARGV]; |
| my ( |
| $err, |
| $new_name, |
| $output, |
| $rerun, |
| $resp, |
| $slurm, |
| $man, |
| $help |
| ); |
| |
| # Remove this |
| my $scontrol = "/usr/slurm/bin/scontrol"; |
| |
| # ------------------------------ |
| # Parse Command Line Arguments |
| # ------------------------------ |
| GetOptions( |
| 'N=s' => \$new_name, |
| 'r=s' => \$rerun, |
| 'o=s' => \$output, |
| 'help|?' => \$help, |
| 'man' => \$man |
| ) |
| or pod2usage(2); |
| |
| pod2usage(0) if $help; |
| |
| if ($man) |
| { |
| if ($< == 0) # Cannot invoke perldoc as root |
| { |
| my $id = eval { getpwnam("nobody") }; |
| $id = eval { getpwnam("nouser") } unless defined $id; |
| $id = -2 unless defined $id; |
| $< = $id; |
| } |
| $> = $<; # Disengage setuid |
| $ENV{PATH} = "/bin:/usr/bin"; # Untaint PATH |
| delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'}; |
| if ($0 =~ /^([-\/\w\.]+)$/) { |
| $0 = $1; # Untaint $0 |
| } else { |
| die "Illegal characters were found in \$0 ($0)\n"; |
| } |
| pod2usage(-exitstatus => 0, -verbose => 2); |
| } |
| |
| # ---------------------- |
| # Check input arguments |
| # ---------------------- |
| if (@ARGV < 1) { |
| pod2usage(-message=>"Missing Job ID", -verbose=>0); |
| } else { |
| $slurm = Slurm::new(); |
| if (!$slurm) { |
| die "Problem loading slurm.\n"; |
| } |
| $resp = $slurm->get_end_time($job_id); |
| if (not defined($resp)) { |
| pod2usage(-message=>"Job id $job_id not valid!", -verbose=>0); |
| } |
| if ((not defined($new_name)) and (not defined($rerun)) and (not defined($output))) { |
| pod2usage(-message=>"no argument given!", -verbose=>0); |
| } |
| } |
| |
| # -------------------------------------------- |
| # Use Slurm's Perl API to change name of a job |
| # -------------------------------------------- |
| if ($new_name) { |
| my %update = (); |
| |
| $update{job_id} = $job_id; |
| $update{name} = $new_name; |
| if (Slurm->update_job(\%update)) { |
| $err = Slurm->get_errno(); |
| $resp = Slurm->strerror($err); |
| pod2usage(-message=>"Job id $job_id name change error: $resp", -verbose=>0); |
| exit(1); |
| } |
| } |
| |
| # --------------------------------------------------- |
| # Use Slurm's Perl API to change the requeue job flag |
| # --------------------------------------------------- |
| if ($rerun) { |
| my %update = (); |
| |
| $update{job_id} = $job_id; |
| if (($rerun eq "n") || ($rerun eq "N")) { |
| $update{requeue} = 0; |
| } else { |
| $update{requeue} = 1; |
| } |
| if (Slurm->update_job(\%update)) { |
| $err = Slurm->get_errno(); |
| $resp = Slurm->strerror($err); |
| pod2usage(-message=>"Job id $job_id requeue error: $resp", -verbose=>0); |
| exit(1); |
| } |
| } |
| |
| # ------------------------------------------------------------ |
| # Use Slurm's Perl API to change Comment string |
| # Comment is used to relocate an output log file |
| # ------------------------------------------------------------ |
| if ($output) { |
| # Example: |
| # $comment="on:16337,stdout=/gpfsm/dhome/lgerner/tmp/slurm-16338.out,stdout=~lgerner/tmp/new16338.out"; |
| # |
| my $comment; |
| my %update = (); |
| |
| # --------------------------------------- |
| # Get current comment string from job_id |
| # --------------------------------------- |
| my($job) = $slurm->load_job($job_id); |
| $comment = $$job{'job_array'}[0]->{comment}; |
| |
| # ---------------- |
| # Split at stdout |
| # ---------------- |
| if ($comment) { |
| my(@outlog) = split("stdout", $comment); |
| |
| # --------------------------------- |
| # Only 1 stdout argument add a ',' |
| # --------------------------------- |
| if ($#outlog < 2) { |
| $outlog[1] .= "," |
| } |
| |
| # ------------------------------------------------ |
| # Add new log file location to the comment string |
| # ------------------------------------------------ |
| $outlog[2] = "=".$output; |
| $comment = join("stdout", @outlog); |
| } else { |
| $comment = "stdout=$output"; |
| } |
| |
| # ------------------------------------------------- |
| # Make sure that "%j" is changed to current $job_id |
| # ------------------------------------------------- |
| $comment =~ s/%j/$job_id/g ; |
| |
| # ----------------------------------------------------- |
| # Update comment and print usage if there is a response |
| # ----------------------------------------------------- |
| $update{job_id} = $job_id; |
| $update{comment} = $comment; |
| if (Slurm->update_job(\%update)) { |
| $err = Slurm->get_errno(); |
| $resp = Slurm->strerror($err); |
| pod2usage(-message=>"Job id $job_id comment change error: $resp", -verbose=>0); |
| exit(1); |
| } |
| } |
| exit(0); |
| |
| ############################################################################## |
| |
| __END__ |
| |
| =head1 NAME |
| |
| B<qalter> - alter a job name, the job rerun flag or the job output file name. |
| |
| =head1 SYNOPSIS |
| |
| qalter [-N Name] |
| [-r y|n] |
| [-o output file] |
| <job ID> |
| |
| =head1 DESCRIPTION |
| |
| The B<qalter> updates job name, job rerun flag or job output(stdout) log location. |
| |
| It is aimed to be feature-compatible with PBS' qsub. |
| |
| =head1 OPTIONS |
| |
| =over 4 |
| |
| =item B<-N> |
| |
| Update job name in the queue |
| |
| =item B<-r> |
| |
| Alter a job rerunnable flag. "y" will allow a qrerun to be issued. "n" disable qrerun option. |
| |
| =item B<-o> |
| |
| Alter a job output log file name (stdout). |
| |
| The job log will be move/rename after the job has B<terminated>. |
| |
| =item B<-?> | B<--help> |
| |
| brief help message |
| |
| =item B<-man> |
| |
| full documentation |
| |
| =back |
| |
| =head1 SEE ALSO |
| |
| qrerun(1) qsub(1) |
| =cut |