mirror of
https://git.savannah.gnu.org/git/parallel.git
synced 2024-11-25 07:27:55 +00:00
Fixed --header bug for multiline headers. +testsuite.
Allow for --timeout 200.5% (float). --workdir . --transfer fixed.
This commit is contained in:
parent
be6fe3846f
commit
6961852117
6
README
6
README
|
@ -30,7 +30,11 @@ The 10 seconds installation will try do to a full installation; if
|
||||||
that fails, a personal installation; if that fails, a minimal
|
that fails, a personal installation; if that fails, a minimal
|
||||||
installation.
|
installation.
|
||||||
|
|
||||||
wget -O - pi.dk/3 | sh
|
wget -O - pi.dk/3 | bash
|
||||||
|
|
||||||
|
or:
|
||||||
|
|
||||||
|
curl pi.dk/3/ | bash
|
||||||
|
|
||||||
This will literally install faster than reading the rest of this
|
This will literally install faster than reading the rest of this
|
||||||
document.
|
document.
|
||||||
|
|
|
@ -209,6 +209,9 @@ New in this release:
|
||||||
http://www.keylength.com/en/4/ the signing key was changed from
|
http://www.keylength.com/en/4/ the signing key was changed from
|
||||||
1024D/ID:FFFFFFF1 to 9888R/ID:88888888.
|
1024D/ID:FFFFFFF1 to 9888R/ID:88888888.
|
||||||
|
|
||||||
|
* Job ad asking for GNU Parallel expertise
|
||||||
|
http://seattle.craigslist.org/est/sof/4006079352.html
|
||||||
|
|
||||||
* Agalma: an automated phylogenomics workflow
|
* Agalma: an automated phylogenomics workflow
|
||||||
http://arxiv.org/pdf/1307.6432
|
http://arxiv.org/pdf/1307.6432
|
||||||
|
|
||||||
|
|
37
src/parallel
37
src/parallel
|
@ -305,12 +305,13 @@ sub spreadstdin {
|
||||||
my $buf = "";
|
my $buf = "";
|
||||||
my $header = "";
|
my $header = "";
|
||||||
if($opt::header) {
|
if($opt::header) {
|
||||||
my $non_greedy_regexp = $opt::header;
|
if($opt::header eq ":") { $opt::header = "(.*\n)"; }
|
||||||
# ? , * , + , {} => ?? , *? , +? , {}?
|
# Number = number of lines
|
||||||
$non_greedy_regexp =~ s/(\?|\*|\+|\})/$1\?/g;
|
$opt::header =~ s/^(\d+)$/"(.*\n)"x$1/e;
|
||||||
while(read(STDIN,substr($buf,length $buf,0),$opt::blocksize)) {
|
while(read(STDIN,substr($buf,length $buf,0),$opt::blocksize)) {
|
||||||
if($buf=~s/^(.*?$non_greedy_regexp)//) {
|
if($buf=~s/^($opt::header)//) {
|
||||||
$header = $1; last;
|
$header = $1;
|
||||||
|
last;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -424,9 +425,8 @@ sub spreadstdin {
|
||||||
$blocksize = ceil($blocksize * 1.3 + 1);
|
$blocksize = ceil($blocksize * 1.3 + 1);
|
||||||
::warning("A full record was not matched in a block. Increasing to --blocksize ".$blocksize."\n");
|
::warning("A full record was not matched in a block. Increasing to --blocksize ".$blocksize."\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# If there is anything left in the buffer write it
|
# If there is anything left in the buffer write it
|
||||||
substr($buf,0,0) = "";
|
substr($buf,0,0) = "";
|
||||||
write_record_to_pipe($chunk_number++,\$header,\$buf,$recstart,$recend,length $buf);
|
write_record_to_pipe($chunk_number++,\$header,\$buf,$recstart,$recend,length $buf);
|
||||||
|
@ -482,7 +482,7 @@ sub round_robin_write {
|
||||||
if($job->stdin_buffer_length() > 0) {
|
if($job->stdin_buffer_length() > 0) {
|
||||||
$something_written += $job->non_block_write();
|
$something_written += $job->non_block_write();
|
||||||
} else {
|
} else {
|
||||||
$job->set_stdin_buffer($block_ref,$endpos,$recstart,$recend);
|
$job->set_stdin_buffer($header_ref,$block_ref,$endpos,$recstart,$recend);
|
||||||
$block_passed = 1;
|
$block_passed = 1;
|
||||||
$job->set_virgin(0);
|
$job->set_virgin(0);
|
||||||
$something_written += $job->non_block_write();
|
$something_written += $job->non_block_write();
|
||||||
|
@ -626,7 +626,7 @@ sub options_hash {
|
||||||
"B=s" => \$opt::retired,
|
"B=s" => \$opt::retired,
|
||||||
"ctrlc|ctrl-c" => \$opt::ctrlc,
|
"ctrlc|ctrl-c" => \$opt::ctrlc,
|
||||||
"noctrlc|no-ctrlc|no-ctrl-c" => \$opt::noctrlc,
|
"noctrlc|no-ctrlc|no-ctrl-c" => \$opt::noctrlc,
|
||||||
"workdir|wd=s" => \$opt::workdir,
|
"workdir|work-dir|wd=s" => \$opt::workdir,
|
||||||
"W=s" => \$opt::retired,
|
"W=s" => \$opt::retired,
|
||||||
"tmpdir=s" => \$opt::tmpdir,
|
"tmpdir=s" => \$opt::tmpdir,
|
||||||
"tempdir=s" => \$opt::tmpdir,
|
"tempdir=s" => \$opt::tmpdir,
|
||||||
|
@ -820,8 +820,9 @@ sub parse_options {
|
||||||
if(defined $opt::fg) { $Global::semaphore = 1; }
|
if(defined $opt::fg) { $Global::semaphore = 1; }
|
||||||
if(defined $opt::bg) { $Global::semaphore = 1; }
|
if(defined $opt::bg) { $Global::semaphore = 1; }
|
||||||
if(defined $opt::wait) { $Global::semaphore = 1; }
|
if(defined $opt::wait) { $Global::semaphore = 1; }
|
||||||
if(defined $opt::timeout and $opt::timeout !~ /^\d+%?$/) {
|
if(defined $opt::timeout and $opt::timeout !~ /^\d+(\.\d+)?%?$/) {
|
||||||
::error("--timeout must be seconds or percentage\n");
|
::error("--timeout must be seconds or percentage\n");
|
||||||
|
wait_and_exit(255);
|
||||||
}
|
}
|
||||||
if(defined $opt::minversion) {
|
if(defined $opt::minversion) {
|
||||||
print $Global::version,"\n";
|
print $Global::version,"\n";
|
||||||
|
@ -3739,8 +3740,8 @@ sub write {
|
||||||
|
|
||||||
sub set_stdin_buffer {
|
sub set_stdin_buffer {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
my ($block_ref,$endpos,$recstart,$recend) = @_;
|
my ($header_ref,$block_ref,$endpos,$recstart,$recend) = @_;
|
||||||
$self->{'stdin_buffer'} = substr($$block_ref,0,$endpos);
|
$self->{'stdin_buffer'} = ($self->virgin() ? $$header_ref : "").substr($$block_ref,0,$endpos);
|
||||||
if($opt::remove_rec_sep) {
|
if($opt::remove_rec_sep) {
|
||||||
remove_rec_sep(\$self->{'stdin_buffer'},$recstart,$recend);
|
remove_rec_sep(\$self->{'stdin_buffer'},$recstart,$recend);
|
||||||
}
|
}
|
||||||
|
@ -3786,10 +3787,11 @@ sub non_block_write {
|
||||||
} else {
|
} else {
|
||||||
# successfully wrote everything
|
# successfully wrote everything
|
||||||
my $a="";
|
my $a="";
|
||||||
$self->set_stdin_buffer(\$a,0,"","");
|
$self->set_stdin_buffer(\$a,\$a,"","");
|
||||||
$something_written = $rv;
|
$something_written = $rv;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
::debug("Non-block: $something_written");
|
::debug("Non-block: $something_written");
|
||||||
return $something_written;
|
return $something_written;
|
||||||
}
|
}
|
||||||
|
@ -4231,7 +4233,7 @@ sub workdir {
|
||||||
my $home = $ENV{'HOME'};
|
my $home = $ENV{'HOME'};
|
||||||
eval 'use Cwd';
|
eval 'use Cwd';
|
||||||
my $cwd = cwd();
|
my $cwd = cwd();
|
||||||
$opt::workdir = $cwd;
|
$workdir = $cwd;
|
||||||
if($home) {
|
if($home) {
|
||||||
# If homedir exists: remove the homedir from
|
# If homedir exists: remove the homedir from
|
||||||
# workdir if cwd starts with homedir
|
# workdir if cwd starts with homedir
|
||||||
|
@ -4247,7 +4249,7 @@ sub workdir {
|
||||||
my ($parent_dev, $parent_ino) = (stat($parent))[0,1];
|
my ($parent_dev, $parent_ino) = (stat($parent))[0,1];
|
||||||
if($parent_dev == $home_dev and $parent_ino == $home_ino) {
|
if($parent_dev == $home_dev and $parent_ino == $home_ino) {
|
||||||
# dev and ino is the same: We found the homedir.
|
# dev and ino is the same: We found the homedir.
|
||||||
$opt::workdir = join("/",@dir_parts);
|
$workdir = join("/",@dir_parts);
|
||||||
last;
|
last;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5842,12 +5844,11 @@ package TimeoutQueue;
|
||||||
sub new {
|
sub new {
|
||||||
my $class = shift;
|
my $class = shift;
|
||||||
my $delta_time = shift;
|
my $delta_time = shift;
|
||||||
my ($pct,$avg_damper);
|
my ($pct);
|
||||||
if($delta_time =~ /(\d+)%/) {
|
if($delta_time =~ /(\d+(\.\d+)?)%/) {
|
||||||
# Timeout in percent
|
# Timeout in percent
|
||||||
$pct = $1/100;
|
$pct = $1/100;
|
||||||
$delta_time = 1_000_000;
|
$delta_time = 1_000_000;
|
||||||
$avg_damper = (1-0.001)/0.9;
|
|
||||||
}
|
}
|
||||||
return bless {
|
return bless {
|
||||||
'queue' => [],
|
'queue' => [],
|
||||||
|
|
|
@ -553,15 +553,18 @@ status will be the exit status from the failing job.
|
||||||
=back
|
=back
|
||||||
|
|
||||||
|
|
||||||
=item B<--header> I<regexp>
|
=item B<--header> I<regexp> (alpha testing)
|
||||||
|
|
||||||
Use upto regexp as header. For normal usage the matched header
|
Use regexp as header. For normal usage the matched header (typically
|
||||||
(typically the first line: B<--header '\n'>) will be split using
|
the first line: B<--header '.*\n'>) will be split using B<--colsep>
|
||||||
B<--colsep> (which will default to '\t') and column names can be used
|
(which will default to '\t') and column names can be used as
|
||||||
as replacement variables: B<{column name}>. For B<--pipe> the matched
|
replacement variables: B<{column name}>.
|
||||||
header will be prepended to each output.
|
|
||||||
|
|
||||||
B<--header :> is an alias for B<--header '\n'>.
|
For B<--pipe> the matched header will be prepended to each output.
|
||||||
|
|
||||||
|
B<--header :> is an alias for B<--header '.*\n'>.
|
||||||
|
|
||||||
|
If I<regexp> is a number, it will match that many lines.
|
||||||
|
|
||||||
|
|
||||||
=item B<-I> I<replace-str>
|
=item B<-I> I<replace-str>
|
||||||
|
|
|
@ -584,16 +584,19 @@ status will be the exit status from the failing job.
|
||||||
|
|
||||||
@end table
|
@end table
|
||||||
|
|
||||||
@item @strong{--header} @emph{regexp}
|
@item @strong{--header} @emph{regexp} (alpha testing)
|
||||||
@anchor{@strong{--header} @emph{regexp}}
|
@anchor{@strong{--header} @emph{regexp} (alpha testing)}
|
||||||
|
|
||||||
Use upto regexp as header. For normal usage the matched header
|
Use regexp as header. For normal usage the matched header (typically
|
||||||
(typically the first line: @strong{--header '\n'}) will be split using
|
the first line: @strong{--header '.*\n'}) will be split using @strong{--colsep}
|
||||||
@strong{--colsep} (which will default to '\t') and column names can be used
|
(which will default to '\t') and column names can be used as
|
||||||
as replacement variables: @strong{@{column name@}}. For @strong{--pipe} the matched
|
replacement variables: @strong{@{column name@}}.
|
||||||
header will be prepended to each output.
|
|
||||||
|
|
||||||
@strong{--header :} is an alias for @strong{--header '\n'}.
|
For @strong{--pipe} the matched header will be prepended to each output.
|
||||||
|
|
||||||
|
@strong{--header :} is an alias for @strong{--header '.*\n'}.
|
||||||
|
|
||||||
|
If @emph{regexp} is a number, it will match that many lines.
|
||||||
|
|
||||||
@item @strong{-I} @emph{replace-str}
|
@item @strong{-I} @emph{replace-str}
|
||||||
@anchor{@strong{-I} @emph{replace-str}}
|
@anchor{@strong{-I} @emph{replace-str}}
|
||||||
|
|
1881
src/parallel_tutorial.html
Normal file
1881
src/parallel_tutorial.html
Normal file
File diff suppressed because it is too large
Load diff
|
@ -33,6 +33,18 @@ stdout /usr/bin/time -f %e parallel --delay 2 true ::: 1 2 3 | perl -ne '$_ >= 4
|
||||||
echo '### Exit value should not be affected if an earlier job times out'
|
echo '### Exit value should not be affected if an earlier job times out'
|
||||||
parallel -j2 --timeout 1 --joblog - -k ::: "sleep 10" "exit 255" | field 7
|
parallel -j2 --timeout 1 --joblog - -k ::: "sleep 10" "exit 255" | field 7
|
||||||
|
|
||||||
|
echo '### --header regexp'
|
||||||
|
(echo %head1; echo %head2; seq 5) | nice parallel -kj2 --pipe -N2 --header '(%.*\n)*' echo JOB{#}\;cat
|
||||||
|
|
||||||
|
echo '### --header num'
|
||||||
|
(echo %head1; echo %head2; seq 5) | nice parallel -kj2 --pipe -N2 --header 2 echo JOB{#}\;cat
|
||||||
|
|
||||||
|
echo '### --header regexp --round-robin'
|
||||||
|
(echo %head1; echo %head2; seq 5) | nice parallel -kj2 --pipe -N2 --round --header '(%.*\n)*' echo JOB{#}\;cat
|
||||||
|
|
||||||
|
echo '### --header num --round-robin'
|
||||||
|
(echo %head1; echo %head2; seq 5) | nice parallel -kj2 --pipe -N2 --round --header 2 echo JOB{#}\;cat
|
||||||
|
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
rm -rf tmp
|
rm -rf tmp
|
||||||
|
|
|
@ -14,3 +14,7 @@ seq 1 100 | parallel --sshlogin "/tmp/myssh1 $SSHLOGIN1, /tmp/myssh2 $SSHLOGIN2"
|
||||||
|
|
||||||
echo '### --filter-hosts - OK, non-such-user, connection refused, wrong host'
|
echo '### --filter-hosts - OK, non-such-user, connection refused, wrong host'
|
||||||
parallel --nonall --filter-hosts -S localhost,NoUser@localhost,154.54.72.206,"ssh 5.5.5.5" hostname
|
parallel --nonall --filter-hosts -S localhost,NoUser@localhost,154.54.72.206,"ssh 5.5.5.5" hostname
|
||||||
|
|
||||||
|
echo '### test --workdir . in $HOME'
|
||||||
|
cd && mkdir parallel-test && cd parallel-test &&
|
||||||
|
echo OK > testfile && parallel --workdir . --transfer -S $SSHLOGIN1 cat {} ::: testfile
|
||||||
|
|
|
@ -52,3 +52,57 @@ OK
|
||||||
Exitval
|
Exitval
|
||||||
-1
|
-1
|
||||||
255
|
255
|
||||||
|
### --header regexp
|
||||||
|
JOB1
|
||||||
|
%head1
|
||||||
|
%head2
|
||||||
|
1
|
||||||
|
2
|
||||||
|
JOB2
|
||||||
|
%head1
|
||||||
|
%head2
|
||||||
|
3
|
||||||
|
4
|
||||||
|
JOB3
|
||||||
|
%head1
|
||||||
|
%head2
|
||||||
|
5
|
||||||
|
### --header num
|
||||||
|
JOB1
|
||||||
|
%head1
|
||||||
|
%head2
|
||||||
|
1
|
||||||
|
2
|
||||||
|
JOB2
|
||||||
|
%head1
|
||||||
|
%head2
|
||||||
|
3
|
||||||
|
4
|
||||||
|
JOB3
|
||||||
|
%head1
|
||||||
|
%head2
|
||||||
|
5
|
||||||
|
### --header regexp --round-robin
|
||||||
|
JOB1
|
||||||
|
%head1
|
||||||
|
%head2
|
||||||
|
3
|
||||||
|
4
|
||||||
|
JOB2
|
||||||
|
%head1
|
||||||
|
%head2
|
||||||
|
1
|
||||||
|
2
|
||||||
|
5
|
||||||
|
### --header num --round-robin
|
||||||
|
JOB1
|
||||||
|
%head1
|
||||||
|
%head2
|
||||||
|
1
|
||||||
|
2
|
||||||
|
5
|
||||||
|
JOB2
|
||||||
|
%head1
|
||||||
|
%head2
|
||||||
|
3
|
||||||
|
4
|
||||||
|
|
Loading…
Reference in a new issue