2 # dqsub submits jobs using qsub with better options
3 # and is released under the terms of the GNU GPL version 3, or any
4 # later version, at your option. See the file README and COPYING for
6 # Copyright 2014 by Don Armstrong <don@donarmstrong.com>.
17 dqsub - submits jobs using qsub with better options
24 --queue, -q Queue to use
25 --interactive, -I call qsub interactively
27 --array array mode (one of 'chdir' or 'xargs' or '')
28 --array-from file to read arrays from (default STDIN)
29 --ppn processors per node to use
30 --mem memory to request
31 --dir Directory to run the script in (default current directory)
32 --debug, -d debugging level (Default 0)
33 --help, -h display this help
34 --man, -m display manual
42 This describes how dqsub will generate array jobs.
44 If no B<--array> is given, then the command and any additional
45 arguments given will be run using qsub.
47 If B<--array> is C<chdir>, then each line of the input given in
48 B<--array-from> will be used as a directory and the command and any
49 additional arguments given will run in each directory.
51 IF B<--array> is C<xargs>, then each line of the input given will be
52 considered to be an additional argument which will be given to the
53 command run in the current directory.
57 File to read array arguments from. If not provided, and B<--array> is
58 given, arguments will be read from STDIN.
62 Debug verbosity. (Default 0)
66 Display brief usage information.
81 use Cwd qw(getcwd abs_path);
84 my %options = (nodes => 1,
98 'array_from|array-from=s',
99 'ppn|processors-per-node=i',
102 'debug|d+','help|h|?','man|m');
104 # pod2usage() if $options{help};
105 # pod2usage({verbose=>2}) if $options{man};
107 $DEBUG = $options{debug};
110 if (not @ARGV and not $options{interactive}) {
111 push @USAGE_ERRORS,"You must provide a command to run";
113 if (defined $options{array} and $options{array} !~ /^(?:|chdir|xargs)$/i) {
114 push @USAGE_ERRORS,"--array must be one of chdir, xargs or '' if provided";
115 $options{array} = lc($options{array});
116 if ($options{array} eq '') {
117 $options{array} = undef;
120 if ($options{interactive} and @ARGV) {
121 push @USAGE_ERRORS,"Don't provide commands when you're asking for an interactive shell";
124 # pod2usage(join("\n",@USAGE_ERRORS)) if @USAGE_ERRORS;
125 print STDERR join("\n",@USAGE_ERRORS) and exit 1 if @USAGE_ERRORS;
127 # OK. Generate the options to qsub which we'll be using
128 my @qsub_options = generate_qsub_options(\%options);
130 if ($options{interactive}) {
131 print STDERR 'running: qsub '.join(' ',@qsub_options) if $DEBUG;
132 exec('qsub',@qsub_options);
135 if ($options{array}) {
136 @array = read_array_options(\%options) if $options{array};
137 # the -t option gives the range of elements for an array job
138 push @qsub_options,'-t','1-'. scalar @array;
140 call_qsub(\@qsub_options,write_qsub_script(\%options,\@ARGV,\@array));
143 sub generate_qsub_options{
146 if (defined $options->{queue} and length $options->{queue}) {
147 push @qo,'-q',$options->{queue};
149 if (defined $options->{dir}) {
150 push @qo,'-d',abs_path($options->{dir});
152 push @qo,'-d',getcwd;
154 ## handle the -l options
156 push @l, 'nodes='.$options->{nodes};
157 if (defined $options->{ppn}) {
158 $l[$#l] .= ':ppn='.$options->{ppn};
160 if ($options->{mem}) {
161 push @l,'mem='.$options->{mem};
163 push @qo,'-l',join(',',@l) if @l;
164 if ($options->{interactive}) {
170 sub read_array_options{
173 if (defined $options->{array_from}) {
174 $fh = IO::File->new(defined $options->{array_from}) or
175 die "Unable to open $options->{array_from} for reading: $!";
186 my ($qsub_options,$script) = @_;
188 open $qsub_fh,'|-','qsub',@{$qsub_options},'-' or
189 die "Unable to start qsub: $!";
190 print {$qsub_fh} $script or
191 die "Unable to print to qsub: $!";
193 die "Unable to close qsub filehandle: $!";
196 sub write_qsub_script {
197 my ($opt,$arg,$array) = @_;
199 my $script = "#!/bin/bash\n";
200 my $command = join(' ',map {qq('$_')} @{$arg});
202 # this script was written by dqsub
204 if (defined $opt->{array}) {
205 my $array_opt = join("\n",@{$array});
207 OPT=\$(sed -n -e "\$PBS_ARRAYID p"<<'_HERE_DOC_END_'
212 if ($opt->{array} eq 'chdir') {
219 exec $command "\$OPT";
224 # there's no array, so just executing the command with arguments