parallel: Fixed bug #42493: --sshlogin does not send stderr to stderr.

This commit is contained in:
Ole Tange 2014-12-30 00:31:02 +01:00
parent 0992d1a7c9
commit 11a05ca1a3
9 changed files with 113 additions and 63 deletions

View file

@ -43,7 +43,7 @@ measure() {
Rscript - <<_ Rscript - <<_
jl<-read.csv("/tmp/joblog.csv",sep="\t"); jl<-read.csv("/tmp/joblog.csv",sep="\t");
jl\$Command <- as.factor(substr(jl\$Command, 13, nchar(as.character(jl\$Command))-5)) jl\$Command <- as.factor(substr(jl\$Command, 12, nchar(as.character(jl\$Command))-5))
pdf("/tmp/boxplot.pdf"); pdf("/tmp/boxplot.pdf");
par(cex.axis=0.5); par(cex.axis=0.5);
boxplot(JobRuntime/$INNER*1000~Command,data=jl,las=2,outline=F, boxplot(JobRuntime/$INNER*1000~Command,data=jl,las=2,outline=F,

View file

@ -295,6 +295,7 @@ sub spreadstdin {
# $Global::start_no_new_jobs # $Global::start_no_new_jobs
# $opt::roundrobin # $opt::roundrobin
# %Global::running # %Global::running
# Returns: N/A
my $buf = ""; my $buf = "";
my ($recstart,$recend) = recstartrecend(); my ($recstart,$recend) = recstartrecend();
@ -476,6 +477,8 @@ sub nindex {
# $endpos = end position of $block # $endpos = end position of $block
# Uses: # Uses:
# %Global::running # %Global::running
# Returns:
# $something_written = amount of bytes written
my ($header_ref,$block_ref,$recstart,$recend,$endpos) = @_; my ($header_ref,$block_ref,$recstart,$recend,$endpos) = @_;
my $something_written = 0; my $something_written = 0;
my $block_passed = 0; my $block_passed = 0;
@ -952,7 +955,7 @@ sub parse_options {
sub init_globals { sub init_globals {
# Defaults: # Defaults:
$Global::version = 20141225; $Global::version = 20141229;
$Global::progname = 'parallel'; $Global::progname = 'parallel';
$Global::infinity = 2**31; $Global::infinity = 2**31;
$Global::debug = 0; $Global::debug = 0;
@ -1107,8 +1110,10 @@ sub parse_env_var {
# Bash functions must be parsed to export them remotely # Bash functions must be parsed to export them remotely
# Pre-shellshock style bash function: # Pre-shellshock style bash function:
# myfunc=() {... # myfunc=() {...
# Post-shellshock style bash function: # Post-shellshock style bash function (v1):
# BASH_FUNC_myfunc()=() {... # BASH_FUNC_myfunc()=() {...
# Post-shellshock style bash function (v2):
# BASH_FUNC_myfunc%%=() {...
# #
# Uses: # Uses:
# $Global::envvar = eval string that will set variables in both bash and csh # $Global::envvar = eval string that will set variables in both bash and csh
@ -1143,7 +1148,7 @@ sub parse_env_var {
} }
# Duplicate vars as BASH functions to include post-shellshock functions. # Duplicate vars as BASH functions to include post-shellshock functions.
# So --env myfunc should also look for BASH_FUNC_myfunc() # So --env myfunc should also look for BASH_FUNC_myfunc()
@vars = map { $_, "BASH_FUNC_$_()" } @vars; @vars = map { $_, "BASH_FUNC_$_()", "BASH_FUNC_$_%%" } @vars;
# Keep only defined variables # Keep only defined variables
@vars = grep { defined($ENV{$_}) } @vars; @vars = grep { defined($ENV{$_}) } @vars;
# Pre-shellshock style bash function: # Pre-shellshock style bash function:
@ -1152,6 +1157,8 @@ sub parse_env_var {
# Post-shellshock style bash function: # Post-shellshock style bash function:
# BASH_FUNC_myfunc()=() { echo myfunc # BASH_FUNC_myfunc()=() { echo myfunc
# } # }
# BASH_FUNC_myfunc%%=() { echo myfunc
# }
my @bash_functions = grep { substr($ENV{$_},0,4) eq "() {" } @vars; my @bash_functions = grep { substr($ENV{$_},0,4) eq "() {" } @vars;
my @non_functions = grep { substr($ENV{$_},0,4) ne "() {" } @vars; my @non_functions = grep { substr($ENV{$_},0,4) ne "() {" } @vars;
if(@bash_functions) { if(@bash_functions) {
@ -1162,9 +1169,9 @@ sub parse_env_var {
} }
# Pre-shellschock names are without () # Pre-shellschock names are without ()
my @bash_pre_shellshock = grep { not /\(\)/ } @bash_functions; my @bash_pre_shellshock = grep { not /\(\)|%%/ } @bash_functions;
# Post-shellschock names are with () # Post-shellschock names are with ()
my @bash_post_shellshock = grep { /\(\)/ } @bash_functions; my @bash_post_shellshock = grep { /\(\)|%%/ } @bash_functions;
my @qcsh = (map { my $a=$_; "setenv $a " . env_quote($ENV{$a}) } my @qcsh = (map { my $a=$_; "setenv $a " . env_quote($ENV{$a}) }
grep { not /^parallel_bash_environment$/ } @non_functions); grep { not /^parallel_bash_environment$/ } @non_functions);
@ -1172,14 +1179,14 @@ sub parse_env_var {
@non_functions, @bash_pre_shellshock); @non_functions, @bash_pre_shellshock);
push @qbash, map { my $a=$_; "eval $a\"\$$a\"" } @bash_pre_shellshock; push @qbash, map { my $a=$_; "eval $a\"\$$a\"" } @bash_pre_shellshock;
push @qbash, map { /BASH_FUNC_(.*)\(\)/; "$1 $ENV{$_}" } @bash_post_shellshock; push @qbash, map { /BASH_FUNC_(.*)(\(\)|%%)/; "$1 $ENV{$_}" } @bash_post_shellshock;
#ssh -tt -oLogLevel=quiet lo 'eval `echo PARALLEL_SEQ='$PARALLEL_SEQ'\;export PARALLEL_SEQ\; PARALLEL_PID='$PARALLEL_PID'\;export PARALLEL_PID` ;' tty\ \>/dev/null\ \&\&\ stty\ isig\ -onlcr\ -echo\;echo\ \$SHELL\ \|\ grep\ \"/t\\\{0,1\\\}csh\"\ \>\ /dev/null\ \&\&\ setenv\ BASH_FUNC_myfunc\ \\\(\\\)\\\ \\\{\\\ \\\ echo\\\ a\"' #ssh -tt -oLogLevel=quiet lo 'eval `echo PARALLEL_SEQ='$PARALLEL_SEQ'\;export PARALLEL_SEQ\; PARALLEL_PID='$PARALLEL_PID'\;export PARALLEL_PID` ;' tty\ \>/dev/null\ \&\&\ stty\ isig\ -onlcr\ -echo\;echo\ \$SHELL\ \|\ grep\ \"/t\\\{0,1\\\}csh\"\ \>\ /dev/null\ \&\&\ setenv\ BASH_FUNC_myfunc\ \\\(\\\)\\\ \\\{\\\ \\\ echo\\\ a\"'
#'\"\\\}\ \|\|\ myfunc\(\)\ \{\ \ echo\ a' #'\"\\\}\ \|\|\ myfunc\(\)\ \{\ \ echo\ a'
#'\}\ \;myfunc\ 1; #'\}\ \;myfunc\ 1;
# Check if any variables contain \n # Check if any variables contain \n
if(my @v = map { s/BASH_FUNC_(.*)\(\)/$1/; $_ } grep { $ENV{$_}=~/\n/ } @vars) { if(my @v = map { s/BASH_FUNC_(.*)(\(\)|%%)/$1/; $_ } grep { $ENV{$_}=~/\n/ } @vars) {
# \n is bad for csh and will cause it to fail. # \n is bad for csh and will cause it to fail.
$Global::envwarn = ::shell_quote_scalar(q{echo $SHELL | egrep "/t?csh" > /dev/null && echo CSH/TCSH DO NOT SUPPORT newlines IN VARIABLES/FUNCTIONS. Unset }."@v".q{ && exec false;}."\n\n") . $Global::envwarn; $Global::envwarn = ::shell_quote_scalar(q{echo $SHELL | egrep "/t?csh" > /dev/null && echo CSH/TCSH DO NOT SUPPORT newlines IN VARIABLES/FUNCTIONS. Unset }."@v".q{ && exec false;}."\n\n") . $Global::envwarn;
} }
@ -4880,7 +4887,7 @@ sub no_of_cpus_qnx {
# Returns: # Returns:
# Number of physical CPUs on QNX # Number of physical CPUs on QNX
# undef if not QNX # undef if not QNX
# BUG: It is now known how to calculate this. # BUG: It is not known how to calculate this.
my $no_of_cpus = 0; my $no_of_cpus = 0;
return $no_of_cpus; return $no_of_cpus;
} }
@ -4889,7 +4896,7 @@ sub no_of_cores_qnx {
# Returns: # Returns:
# Number of CPU cores on QNX # Number of CPU cores on QNX
# undef if not QNX # undef if not QNX
# BUG: It is now known how to calculate this. # BUG: It is not known how to calculate this.
my $no_of_cores = 0; my $no_of_cores = 0;
return $no_of_cores; return $no_of_cores;
} }
@ -5221,10 +5228,10 @@ sub new {
return bless { return bless {
'commandline' => $commandlineref, # CommandLine object 'commandline' => $commandlineref, # CommandLine object
'workdir' => undef, # --workdir 'workdir' => undef, # --workdir
'stdin' => undef, # filehandle for stdin (used for --pipe) # filehandle for stdin (used for --pipe)
# filename for writing stdout to (used for --files) # filename for writing stdout to (used for --files)
'remaining' => "", # remaining data not sent to stdin (used for --pipe) # remaining data not sent to stdin (used for --pipe)
'datawritten' => 0, # amount of data sent via stdin (used for --pipe) # amount of data sent via stdin (used for --pipe)
'transfersize' => 0, # size of files using --transfer 'transfersize' => 0, # size of files using --transfer
'returnsize' => 0, # size of files using --return 'returnsize' => 0, # size of files using --return
'pid' => undef, 'pid' => undef,
@ -5540,15 +5547,9 @@ sub non_block_write {
my $self = shift; my $self = shift;
my $something_written = 0; my $something_written = 0;
use POSIX qw(:errno_h); use POSIX qw(:errno_h);
# use Fcntl; # for loop used to avoid copying substr: $buf will be an alias for the substr
# my $flags = '';
for my $buf (substr($self->{'stdin_buffer'},$self->{'stdin_buffer_pos'})) { for my $buf (substr($self->{'stdin_buffer'},$self->{'stdin_buffer_pos'})) {
my $in = $self->fh(0,"w"); my $in = $self->fh(0,"w");
# fcntl($in, F_GETFL, $flags)
# or die "Couldn't get flags for HANDLE : $!\n";
# $flags |= O_NONBLOCK;
# fcntl($in, F_SETFL, $flags)
# or die "Couldn't set flags for HANDLE: $!\n";
my $rv = syswrite($in, $buf); my $rv = syswrite($in, $buf);
if (!defined($rv) && $! == EAGAIN) { if (!defined($rv) && $! == EAGAIN) {
# would block # would block
@ -5875,6 +5876,49 @@ sub sshlogin_wrap {
# Wrap the command with the commands needed to run remotely # Wrap the command with the commands needed to run remotely
# Returns: # Returns:
# $self->{'sshlogin_wrap'} = command wrapped with ssh+transfer commands # $self->{'sshlogin_wrap'} = command wrapped with ssh+transfer commands
sub monitor_parent_sshd_script {
# This script is to solve the problem of
# * not mixing STDERR and STDOUT
# * terminating with ctrl-c
# If its parent is ssh: all good
# If its parent is init(1): ssh died, so kill children
my $monitor_parent_sshd_script;
if(not $monitor_parent_sshd_script) {
$monitor_parent_sshd_script =
# This will be packed in ', so only use "
q{
# If packed as hex, unpack
# if($ARGV[0] =~ s/^0x//) {
# $ARGV[0] =~ s/(..)/chr(hex $1)/ge;
#}
$SIG{CHLD} = sub { $done = 1; };
$pid = fork;
unless($pid) {
# Make own process group to be able to kill HUP it later
setpgrp;
exec $ENV{SHELL}, "-c", @ARGV;
die "exec: $!\n";
}
do {
# Parent is not init (ppid=1), so sshd is alive
# Exponential sleep up to 1 sec
$s = $s < 1 ? 0.001 + $s * 1.03 : $s;
select(undef, undef, undef, $s);
} until ($done || getppid == 1);
# Kill HUP the process group if job not done
kill(SIGHUP, -${pid}) unless $done;
wait;
exit ($?&127 ? 128+($?&127) : 1+$?>>8)
};
$monitor_parent_sshd_script =~ s/#.*//mg;
$monitor_parent_sshd_script =~ s/\s//mg;
}
return $monitor_parent_sshd_script;
}
#sub hex_pack {
#return unpack("H*","@_");
#}
my $self = shift; my $self = shift;
my $command = shift; my $command = shift;
if(not defined $self->{'sshlogin_wrap'}) { if(not defined $self->{'sshlogin_wrap'}) {
@ -5913,17 +5957,16 @@ sub sshlogin_wrap {
if(($opt::pipe or $opt::pipepart) and $opt::ctrlc if(($opt::pipe or $opt::pipepart) and $opt::ctrlc
or or
not ($opt::pipe or $opt::pipepart) and not $opt::noctrlc) { not ($opt::pipe or $opt::pipepart) and not $opt::noctrlc) {
# TODO Determine if this is needed
# Propagating CTRL-C to kill remote jobs requires # Propagating CTRL-C to kill remote jobs requires
# remote jobs to be run with a terminal. # remote jobs to be run with a terminal.
$ssh_options = "-tt -oLogLevel=quiet"; # $ssh_options = "-tt -oLogLevel=quiet";
# $ssh_options = ""; $ssh_options = "";
# tty - check if we have a tty. # tty - check if we have a tty.
# stty: # stty:
# -onlcr - make output 8-bit clean # -onlcr - make output 8-bit clean
# isig - pass CTRL-C as signal # isig - pass CTRL-C as signal
# -echo - do not echo input # -echo - do not echo input
$remote_pre .= ::shell_quote_scalar('tty >/dev/null && stty isig -onlcr -echo;'); # $remote_pre .= ::shell_quote_scalar('tty >/dev/null && stty isig -onlcr -echo;');
} }
if($opt::workdir) { if($opt::workdir) {
my $wd = ::shell_quote_file($self->workdir()); my $wd = ::shell_quote_file($self->workdir());
@ -5933,34 +5976,43 @@ sub sshlogin_wrap {
# but that fails on tcsh # but that fails on tcsh
::shell_quote_scalar(qq{ || exec false;}); ::shell_quote_scalar(qq{ || exec false;});
} }
# This script is to solve the problem of my $signal_script = "exec perl -e '".monitor_parent_sshd_script()."' ";
# * not mixing STDERR and STDOUT # TODO clean this up
# * terminating with ctrl-c # TODO Maybe env vars should be set in the perl script
# It works on Linux but not Solaris # It works on Linux but not Solaris
# Finishes on Solaris, but wrong exit code: # Finishes on Solaris, but wrong exit code:
# $SIG{CHLD} = sub {exit ($?&127 ? 128+($?&127) : 1+$?>>8)}; # $SIG{CHLD} = sub {exit ($?&127 ? 128+($?&127) : 1+$?>>8)};
# Hangs on Solaris, but correct exit code on Linux: # Hangs on Solaris, but correct exit code on Linux:
# $SIG{CHLD} = sub { $done = 1 }; # $SIG{CHLD} = sub { $done = 1 };
# $p->poll; # $p->poll;
my $signal_script = "perl -e '".
q{ # $SIG{CHLD} = sub { $done = 1; ($^O eq "solaris") && exit 0 };
use IO::Poll; # $SIG{CHLD} = sub { $done = 1; (1) && exit ($?&127 ? 128+($?&127) : 1+$?>>8); };
$SIG{CHLD} = sub { $done = 1 }; # $SIG{CHLD} = sub { $done = 1; exit ($?&127 ? 128+($?&127) : 1+$?>>8); };
$p = IO::Poll->new; # -> Linux: "" +script
$p->mask(STDOUT, POLLHUP); # -> Solaris: -tt -script
$pid=fork; unless($pid) {setpgrp; exec $ENV{SHELL}, "-c", @ARGV; die "exec: $!\n"} # --ctrl-c => -tt
$p->poll; # q{
kill SIGHUP, -${pid} unless $done; # ($^O eq "solaris") && exec $ENV{SHELL}, "-c", @ARGV;
wait; exit ($?&127 ? 128+($?&127) : 1+$?>>8) # $|=1;
} . "' "; # use IO::Poll;
$signal_script =~ s/\s+/ /g; # $SIG{CHLD} = sub {$done = 1; };
# $pid=fork; unless($pid) {setpgrp; exec $ENV{SHELL}, "-c", @ARGV; die "exec: $!\n"}
# $p = IO::Poll->new;
# $p->mask(STDOUT, POLLHUP);
# $p->poll;
# kill SIGHUP, -${pid} unless $done;
# wait; exit ($?&127 ? 128+($?&127) : 1+$?>>8)
# } . "' ";
# $signal_script =~ s/\s+/ /g;
$self->{'sshlogin_wrap'} = $self->{'sshlogin_wrap'} =
($pre ($pre
. "$sshcmd $ssh_options $serverlogin $parallel_env " . "$sshcmd $ssh_options $serverlogin $parallel_env "
. $remote_pre . $remote_pre
# . ::shell_quote_scalar($signal_script . ::shell_quote_scalar($command)) . ::shell_quote_scalar($signal_script . ::shell_quote_scalar($command))
. ::shell_quote_scalar($command) # . ::shell_quote_scalar($signal_script . hex_pack($command))
# . ::shell_quote_scalar($command)
. ";" . ";"
. $post); . $post);
} }

View file

@ -80,5 +80,5 @@ portable:
timings: tests-to-run/* ../src/parallel timings: tests-to-run/* ../src/parallel
ls tests-to-run/*.sh | parallel echo /usr/bin/time -f %e bash >/tmp/timing.script ls tests-to-run/*.sh | parallel echo /usr/bin/time -f %e bash >/tmp/timing.script
stdout bash -x /tmp/timing.script | tee /tmp/timing.out stdout bash -x /tmp/timing.script | tee /tmp/timing.out
echo usr.bin.time_END >>/tmp/timing.out echo + .usr.bin.time_END >>/tmp/timing.out
perl -ne '/usr.bin.time/ and do { print $$last.$$h; $$h=$$_ }; chomp; $$last = $$_' /tmp/timing.out | sort -n >timings perl -ne '/\+ .usr.bin.time/ and do { print $$last.$$h; $$h=$$_ }; chomp; s/.*\0//;$$last = $$_' /tmp/timing.out |sort -n >timings

View file

@ -59,9 +59,7 @@ bash -c 'echo bug \#43358: shellshock breaks exporting functions using --env _;
bug #43358: shellshock breaks exporting functions using --env _ bug #43358: shellshock breaks exporting functions using --env _
Non-shellshock-hardened to non-shellshock-hardened Non-shellshock-hardened to non-shellshock-hardened
Function non-shellshock-hardened Function non-shellshock-hardened
tcgetattr: Inappropriate ioctl for device
bash -c 'echo bug \#43358: shellshock breaks exporting functions using --env _; echo Non-shellshock-hardened to shellshock-hardened; funky() { echo Function $1; }; export -f funky; parallel --env funky -S parallel@192.168.1.72 funky ::: shellshock-hardened' bash -c 'echo bug \#43358: shellshock breaks exporting functions using --env _; echo Non-shellshock-hardened to shellshock-hardened; funky() { echo Function $1; }; export -f funky; parallel --env funky -S parallel@192.168.1.72 funky ::: shellshock-hardened'
bug #43358: shellshock breaks exporting functions using --env _ bug #43358: shellshock breaks exporting functions using --env _
Non-shellshock-hardened to shellshock-hardened Non-shellshock-hardened to shellshock-hardened
Function shellshock-hardened Function shellshock-hardened
tcgetattr: Inappropriate ioctl for device

View file

@ -754,7 +754,7 @@ args on cmdline
\nice -n1 /bin/bash -c PAR=a\ bash\ -c\ \"echo\ \ \\\$PAR\ b\" \nice -n1 /bin/bash -c PAR=a\ bash\ -c\ \"echo\ \ \\\$PAR\ b\"
a b a b
### Test --nice remote ### Test --nice remote
ssh -tt -oLogLevel=quiet one-server 'eval `echo $SHELL | grep "/t\{0,1\}csh" > /dev/null && echo setenv PARALLEL_SEQ '$PARALLEL_SEQ'\; setenv PARALLEL_PID '$PARALLEL_PID' || echo PARALLEL_SEQ='$PARALLEL_SEQ'\;export PARALLEL_SEQ\; PARALLEL_PID='$PARALLEL_PID'\;export PARALLEL_PID` ;' tty\ \>/dev/null\ \&\&\ stty\ isig\ -onlcr\ -echo\;\\nice\ -n1\ /bin/bash\ -c\ PAR=a\\\ bash\\\ -c\\\ \\\"echo\\\ \\\ \\\\\\\$PAR\\\ b\\\"; ssh one-server 'eval `echo $SHELL | grep "/t\{0,1\}csh" > /dev/null && echo setenv PARALLEL_SEQ '$PARALLEL_SEQ'\; setenv PARALLEL_PID '$PARALLEL_PID' || echo PARALLEL_SEQ='$PARALLEL_SEQ'\;export PARALLEL_SEQ\; PARALLEL_PID='$PARALLEL_PID'\;export PARALLEL_PID` ;' exec\ perl\ -e\ \'\$SIG\{CHLD\}=sub\{\$done=1\;\}\;\$pid=fork\;unless\(\$pid\)\{setpgrp\;exec\$ENV\{SHELL\},\"-c\",@ARGV\;die\"exec:\$\!\\n\"\;\}do\{\$s=\$s\<1\?0.001+\$s\*1.03:\$s\;select\(undef,undef,undef,\$s\)\;\}until\(\$done\|\|getppid==1\)\;kill\(SIGHUP,-\$\{pid\}\)unless\$done\;wait\;exit\(\$\?\&127\?128+\(\$\?\&127\):1+\$\?\>\>8\)\'\ \\\\nice\\\ -n1\\\ /bin/bash\\\ -c\\\ PAR=a\\\\\\\ bash\\\\\\\ -c\\\\\\\ \\\\\\\"echo\\\\\\\ \\\\\\\ \\\\\\\\\\\\\\\$PAR\\\\\\\ b\\\\\\\";
a b a b
### Test distribute arguments at EOF to 2 jobslots ### Test distribute arguments at EOF to 2 jobslots
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34

View file

@ -77,11 +77,11 @@ OK
Input for ssh Input for ssh
parallel@parallel-server1 mkdir -p ./. parallel@parallel-server1 mkdir -p ./.
-l parallel parallel-server1 rsync --server -lDrRze.iLsfx . ./. -l parallel parallel-server1 rsync --server -lDrRze.iLsfx . ./.
-tt -oLogLevel=quiet parallel@parallel-server1 eval `echo $SHELL | grep "/t\{0,1\}csh" > /dev/null && echo setenv PARALLEL_SEQ X\; setenv PARALLEL_PID 00000 || echo PARALLEL_SEQ=X\;export PARALLEL_SEQ\; PARALLEL_PID=00000\;export PARALLEL_PID` ; tty >/dev/null && stty isig -onlcr -echo;cat tmp/parallel.file.' parallel@parallel-server1 eval `echo $SHELL | grep "/t\{0,1\}csh" > /dev/null && echo setenv PARALLEL_SEQ X\; setenv PARALLEL_PID 00000 || echo PARALLEL_SEQ=X\;export PARALLEL_SEQ\; PARALLEL_PID=00000\;export PARALLEL_PID` ; exec perl -e '$SIG{CHLD}=sub{$done=1;};$pid=fork;unless($pid){setpgrp;exec$ENV{SHELL},"-c",@ARGV;die"exec:$!\n";}do{$s=$s<1?0.001+$s*1.03:$s;select(undef,undef,undef,$s);}until($done||getppid==1);kill(SIGHUP,-${pid})unless$done;wait;exit($?&127?128+($?&127):1+$?>>8)' cat\ tmp/parallel.file.\''
'newlineX > tmp/parallel.file.' '\'newlineX\ \>\ tmp/parallel.file.\''
'newlineX.out;cat tmp/parallel.file.' '\'newlineX.out\;cat\ tmp/parallel.file.\''
'newlineX > tmp/parallel.file.' '\'newlineX\ \>\ tmp/parallel.file.\''
'newlineX.out2 '\'newlineX.out2
-l parallel parallel-server1 cd ././tmp; rsync --server --sender -lDrRze.iLsfx . ./parallel.file.' -l parallel parallel-server1 cd ././tmp; rsync --server --sender -lDrRze.iLsfx . ./parallel.file.'
'newlineX.out 'newlineX.out
-l parallel parallel-server1 cd ././tmp; rsync --server --sender -lDrRze.iLsfx . ./parallel.file.' -l parallel parallel-server1 cd ././tmp; rsync --server --sender -lDrRze.iLsfx . ./parallel.file.'
@ -94,11 +94,11 @@ parallel@parallel-server1 (rm -f ./tmp/parallel.file.'
'newlineX.out2; rmdir ./tmp/ ./ 2>/dev/null;) 'newlineX.out2; rmdir ./tmp/ ./ 2>/dev/null;)
parallel@parallel-server2 mkdir -p ./. parallel@parallel-server2 mkdir -p ./.
-l parallel parallel-server2 rsync --server -lDrRze.iLsfx . ./. -l parallel parallel-server2 rsync --server -lDrRze.iLsfx . ./.
-tt -oLogLevel=quiet parallel@parallel-server2 eval `echo $SHELL | grep "/t\{0,1\}csh" > /dev/null && echo setenv PARALLEL_SEQ X\; setenv PARALLEL_PID 00000 || echo PARALLEL_SEQ=X\;export PARALLEL_SEQ\; PARALLEL_PID=00000\;export PARALLEL_PID` ; tty >/dev/null && stty isig -onlcr -echo;cat tmp/parallel.file.' parallel@parallel-server2 eval `echo $SHELL | grep "/t\{0,1\}csh" > /dev/null && echo setenv PARALLEL_SEQ X\; setenv PARALLEL_PID 00000 || echo PARALLEL_SEQ=X\;export PARALLEL_SEQ\; PARALLEL_PID=00000\;export PARALLEL_PID` ; exec perl -e '$SIG{CHLD}=sub{$done=1;};$pid=fork;unless($pid){setpgrp;exec$ENV{SHELL},"-c",@ARGV;die"exec:$!\n";}do{$s=$s<1?0.001+$s*1.03:$s;select(undef,undef,undef,$s);}until($done||getppid==1);kill(SIGHUP,-${pid})unless$done;wait;exit($?&127?128+($?&127):1+$?>>8)' cat\ tmp/parallel.file.\''
'newlineX > tmp/parallel.file.' '\'newlineX\ \>\ tmp/parallel.file.\''
'newlineX.out;cat tmp/parallel.file.' '\'newlineX.out\;cat\ tmp/parallel.file.\''
'newlineX > tmp/parallel.file.' '\'newlineX\ \>\ tmp/parallel.file.\''
'newlineX.out2 '\'newlineX.out2
-l parallel parallel-server2 cd ././tmp; rsync --server --sender -lDrRze.iLsfx . ./parallel.file.' -l parallel parallel-server2 cd ././tmp; rsync --server --sender -lDrRze.iLsfx . ./parallel.file.'
'newlineX.out 'newlineX.out
-l parallel parallel-server2 cd ././tmp; rsync --server --sender -lDrRze.iLsfx . ./parallel.file.' -l parallel parallel-server2 cd ././tmp; rsync --server --sender -lDrRze.iLsfx . ./parallel.file.'

View file

@ -42,7 +42,7 @@ echo /dev/fd/62
/dev/fd/62 /dev/fd/62
echo foo echo foo
foo foo
ssh parallel@redhat9.tange.dk ssh -tt -oLogLevel=quiet centos3.tange.dk 'eval `echo $SHELL | grep "/t\{0,1\}csh" > /dev/null && echo setenv PARALLEL_SEQ '$PARALLEL_SEQ'\; setenv PARALLEL_PID '$PARALLEL_PID' || echo PARALLEL_SEQ='$PARALLEL_SEQ'\;export PARALLEL_SEQ\; PARALLEL_PID='$PARALLEL_PID'\;export PARALLEL_PID` ;' tty\ \>/dev/null\ \&\&\ stty\ isig\ -onlcr\ -echo\;perl\ -pe\ \"\\\$a=1\;\ print\ \\\$a\"\ \<\(echo\ foo\); ssh parallel@redhat9.tange.dk ssh centos3.tange.dk 'eval `echo $SHELL | grep "/t\{0,1\}csh" > /dev/null && echo setenv PARALLEL_SEQ '$PARALLEL_SEQ'\; setenv PARALLEL_PID '$PARALLEL_PID' || echo PARALLEL_SEQ='$PARALLEL_SEQ'\;export PARALLEL_SEQ\; PARALLEL_PID='$PARALLEL_PID'\;export PARALLEL_PID` ;' exec\ perl\ -e\ \'\$SIG\{CHLD\}=sub\{\$done=1\;\}\;\$pid=fork\;unless\(\$pid\)\{setpgrp\;exec\$ENV\{SHELL\},\"-c\",@ARGV\;die\"exec:\$\!\\n\"\;\}do\{\$s=\$s\<1\?0.001+\$s\*1.03:\$s\;select\(undef,undef,undef,\$s\)\;\}until\(\$done\|\|getppid==1\)\;kill\(SIGHUP,-\$\{pid\}\)unless\$done\;wait\;exit\(\$\?\&127\?128+\(\$\?\&127\):1+\$\?\>\>8\)\'\ perl\\\ -pe\\\ \\\"\\\\\\\$a=1\\\;\\\ print\\\ \\\\\\\$a\\\"\\\ \\\<\\\(echo\\\ foo\\\);
1foo 1foo
### Test quoting of $ in command from profile file ### Test quoting of $ in command from profile file
perl -pe '$a=1; print $a' <(echo foo) perl -pe '$a=1; print $a' <(echo foo)

View file

@ -1,15 +1,15 @@
echo '### Test --return of weirdly named file' echo '### Test --return of weirdly named file'
### Test --return of weirdly named file ### Test --return of weirdly named file
stdout parallel --return {} -vv -S parallel\@parallel-server3 echo '>'{} ::: 'aa<${#}" b'; rm 'aa<${#}" b' stdout parallel --return {} -vv -S parallel\@parallel-server3 echo '>'{} ::: 'aa<${#}" b'; rm 'aa<${#}" b'
ssh -tt -oLogLevel=quiet parallel@parallel-server3 'eval `echo $SHELL | grep "/t\{0,1\}csh" > /dev/null && echo setenv PARALLEL_SEQ '$PARALLEL_SEQ'\; setenv PARALLEL_PID '$PARALLEL_PID' || echo PARALLEL_SEQ='$PARALLEL_SEQ'\;export PARALLEL_SEQ\; PARALLEL_PID='$PARALLEL_PID'\;export PARALLEL_PID` ;' tty\ \>/dev/null\ \&\&\ stty\ isig\ -onlcr\ -echo\;echo\ \>aa\\\<\\\$\\\{\\\#\\\}\\\"\\\ b;_EXIT_status=$?; mkdir -p ./.; rsync --protocol 30 --rsync-path=cd\ ././.\;\ rsync -rlDzR -essh parallel@parallel-server3:./aa\\\<\\\$\\\{\\\#\\\}\\\"\\\ b ./.; exit $_EXIT_status; ssh parallel@parallel-server3 'eval `echo $SHELL | grep "/t\{0,1\}csh" > /dev/null && echo setenv PARALLEL_SEQ '$PARALLEL_SEQ'\; setenv PARALLEL_PID '$PARALLEL_PID' || echo PARALLEL_SEQ='$PARALLEL_SEQ'\;export PARALLEL_SEQ\; PARALLEL_PID='$PARALLEL_PID'\;export PARALLEL_PID` ;' exec\ perl\ -e\ \'\$SIG\{CHLD\}=sub\{\$done=1\;\}\;\$pid=fork\;unless\(\$pid\)\{setpgrp\;exec\$ENV\{SHELL\},\"-c\",@ARGV\;die\"exec:\$\!\\n\"\;\}do\{\$s=\$s\<1\?0.001+\$s\*1.03:\$s\;select\(undef,undef,undef,\$s\)\;\}until\(\$done\|\|getppid==1\)\;kill\(SIGHUP,-\$\{pid\}\)unless\$done\;wait\;exit\(\$\?\&127\?128+\(\$\?\&127\):1+\$\?\>\>8\)\'\ echo\\\ \\\>aa\\\\\\\<\\\\\\\$\\\\\\\{\\\\\\\#\\\\\\\}\\\\\\\"\\\\\\\ b;_EXIT_status=$?; mkdir -p ./.; rsync --protocol 30 --rsync-path=cd\ ././.\;\ rsync -rlDzR -essh parallel@parallel-server3:./aa\\\<\\\$\\\{\\\#\\\}\\\"\\\ b ./.; exit $_EXIT_status;
echo '### Test if remote login shell is csh' echo '### Test if remote login shell is csh'
### Test if remote login shell is csh ### Test if remote login shell is csh
stdout parallel -k -vv -S csh@localhost 'echo $PARALLEL_PID $PARALLEL_SEQ {}| wc -w' ::: a b c stdout parallel -k -vv -S csh@localhost 'echo $PARALLEL_PID $PARALLEL_SEQ {}| wc -w' ::: a b c
ssh -tt -oLogLevel=quiet csh@localhost 'eval `echo $SHELL | grep "/t\{0,1\}csh" > /dev/null && echo setenv PARALLEL_SEQ '$PARALLEL_SEQ'\; setenv PARALLEL_PID '$PARALLEL_PID' || echo PARALLEL_SEQ='$PARALLEL_SEQ'\;export PARALLEL_SEQ\; PARALLEL_PID='$PARALLEL_PID'\;export PARALLEL_PID` ;' tty\ \>/dev/null\ \&\&\ stty\ isig\ -onlcr\ -echo\;echo\ \$PARALLEL_PID\ \$PARALLEL_SEQ\ a\|\ wc\ -w; ssh csh@localhost 'eval `echo $SHELL | grep "/t\{0,1\}csh" > /dev/null && echo setenv PARALLEL_SEQ '$PARALLEL_SEQ'\; setenv PARALLEL_PID '$PARALLEL_PID' || echo PARALLEL_SEQ='$PARALLEL_SEQ'\;export PARALLEL_SEQ\; PARALLEL_PID='$PARALLEL_PID'\;export PARALLEL_PID` ;' exec\ perl\ -e\ \'\$SIG\{CHLD\}=sub\{\$done=1\;\}\;\$pid=fork\;unless\(\$pid\)\{setpgrp\;exec\$ENV\{SHELL\},\"-c\",@ARGV\;die\"exec:\$\!\\n\"\;\}do\{\$s=\$s\<1\?0.001+\$s\*1.03:\$s\;select\(undef,undef,undef,\$s\)\;\}until\(\$done\|\|getppid==1\)\;kill\(SIGHUP,-\$\{pid\}\)unless\$done\;wait\;exit\(\$\?\&127\?128+\(\$\?\&127\):1+\$\?\>\>8\)\'\ echo\\\ \\\$PARALLEL_PID\\\ \\\$PARALLEL_SEQ\\\ a\\\|\\\ wc\\\ -w;
3 3
ssh -tt -oLogLevel=quiet csh@localhost 'eval `echo $SHELL | grep "/t\{0,1\}csh" > /dev/null && echo setenv PARALLEL_SEQ '$PARALLEL_SEQ'\; setenv PARALLEL_PID '$PARALLEL_PID' || echo PARALLEL_SEQ='$PARALLEL_SEQ'\;export PARALLEL_SEQ\; PARALLEL_PID='$PARALLEL_PID'\;export PARALLEL_PID` ;' tty\ \>/dev/null\ \&\&\ stty\ isig\ -onlcr\ -echo\;echo\ \$PARALLEL_PID\ \$PARALLEL_SEQ\ b\|\ wc\ -w; ssh csh@localhost 'eval `echo $SHELL | grep "/t\{0,1\}csh" > /dev/null && echo setenv PARALLEL_SEQ '$PARALLEL_SEQ'\; setenv PARALLEL_PID '$PARALLEL_PID' || echo PARALLEL_SEQ='$PARALLEL_SEQ'\;export PARALLEL_SEQ\; PARALLEL_PID='$PARALLEL_PID'\;export PARALLEL_PID` ;' exec\ perl\ -e\ \'\$SIG\{CHLD\}=sub\{\$done=1\;\}\;\$pid=fork\;unless\(\$pid\)\{setpgrp\;exec\$ENV\{SHELL\},\"-c\",@ARGV\;die\"exec:\$\!\\n\"\;\}do\{\$s=\$s\<1\?0.001+\$s\*1.03:\$s\;select\(undef,undef,undef,\$s\)\;\}until\(\$done\|\|getppid==1\)\;kill\(SIGHUP,-\$\{pid\}\)unless\$done\;wait\;exit\(\$\?\&127\?128+\(\$\?\&127\):1+\$\?\>\>8\)\'\ echo\\\ \\\$PARALLEL_PID\\\ \\\$PARALLEL_SEQ\\\ b\\\|\\\ wc\\\ -w;
3 3
ssh -tt -oLogLevel=quiet csh@localhost 'eval `echo $SHELL | grep "/t\{0,1\}csh" > /dev/null && echo setenv PARALLEL_SEQ '$PARALLEL_SEQ'\; setenv PARALLEL_PID '$PARALLEL_PID' || echo PARALLEL_SEQ='$PARALLEL_SEQ'\;export PARALLEL_SEQ\; PARALLEL_PID='$PARALLEL_PID'\;export PARALLEL_PID` ;' tty\ \>/dev/null\ \&\&\ stty\ isig\ -onlcr\ -echo\;echo\ \$PARALLEL_PID\ \$PARALLEL_SEQ\ c\|\ wc\ -w; ssh csh@localhost 'eval `echo $SHELL | grep "/t\{0,1\}csh" > /dev/null && echo setenv PARALLEL_SEQ '$PARALLEL_SEQ'\; setenv PARALLEL_PID '$PARALLEL_PID' || echo PARALLEL_SEQ='$PARALLEL_SEQ'\;export PARALLEL_SEQ\; PARALLEL_PID='$PARALLEL_PID'\;export PARALLEL_PID` ;' exec\ perl\ -e\ \'\$SIG\{CHLD\}=sub\{\$done=1\;\}\;\$pid=fork\;unless\(\$pid\)\{setpgrp\;exec\$ENV\{SHELL\},\"-c\",@ARGV\;die\"exec:\$\!\\n\"\;\}do\{\$s=\$s\<1\?0.001+\$s\*1.03:\$s\;select\(undef,undef,undef,\$s\)\;\}until\(\$done\|\|getppid==1\)\;kill\(SIGHUP,-\$\{pid\}\)unless\$done\;wait\;exit\(\$\?\&127\?128+\(\$\?\&127\):1+\$\?\>\>8\)\'\ echo\\\ \\\$PARALLEL_PID\\\ \\\$PARALLEL_SEQ\\\ c\\\|\\\ wc\\\ -w;
3 3
echo '### Test {} multiple times in different commands' echo '### Test {} multiple times in different commands'
### Test {} multiple times in different commands ### Test {} multiple times in different commands