Pipe input over several scripts

S

spoertsch

Hi,

I'm executing a script with an IPC::eek:pen2 call and pipe some input
parameter in it. So that works fine. That script uses some of the
input paramter and has to pipe the rest to another script that is
started by that script. And that is the part where it doesn't work
anymore. The last script is startet using a system() call:

scriptA starts scriptB with open2
scriptB starts scriptC with system
scriptA passes input for scriptB and scriptC to scriptB
How to pass the input from scriptB to scriptC?

The whole thing is needed to achieve an automation for an installation
process which has several scripts. The problem is that i cant change
too much on scriptB, because it should still work for a manual
installation.
Normally scriptB and scriptC ask for some input on stdin and now i
have to pass the predefined input to those scripts for the automation
without changing the manual installation.


Thanks
spoertsch
 
X

xhoster

spoertsch said:
Hi,

I'm executing a script with an IPC::eek:pen2 call and pipe some input
parameter in it. So that works fine. That script uses some of the
input paramter and has to pipe the rest to another script that is
started by that script. And that is the part where it doesn't work
anymore. The last script is startet using a system() call:

scriptA starts scriptB with open2
scriptB starts scriptC with system
scriptA passes input for scriptB and scriptC to scriptB
How to pass the input from scriptB to scriptC?

Post three short scripts which illustrate this, and whatever problem you
are having with it. The only problem I see is with deadlock--avoid that
and it should just work.

Xho

--
-------------------- http://NewsReader.Com/ --------------------
The costs of publication of this article were defrayed in part by the
payment of page charges. This article must therefore be hereby marked
advertisement in accordance with 18 U.S.C. Section 1734 solely to indicate
this fact.
 
S

spoertsch

Hi,

The problem is that script c is not getting the input.

Script A:
#!/usr/bin/perl
use strict;
use warnings;
use IPC::Open2;

my @input = ('test1', 'test2', 'test3', 'test4');
my $out = "";
my $timeout = 7200;
my $RDR;
my $WTR;
my $cmd = 'perl script_b.pl';

my $pid = open2($RDR,$WTR, $cmd) || die("ERROR: Could not execute: " .
$cmd);

foreach (@input){
print $WTR $_."\n";
}
close($WTR);

if (defined $RDR) {
while (<$RDR>) {
$out .= $_;
}
}
print "\n\n";
print $out;
wait; # wait till prozess with $pid dies
print "Script A finished\n";



Script B:
#!/usr/bin/perl
use strict;
use warnings;
my $input = '';

print "Input 1: ";
chomp($input = <STDIN>);
print $input."\n";

print "Input 2: ";
chomp($input = <STDIN>);
print $input."\n";

system('perl script_c.pl');
print "Script B finished\n";



Script C:
#!/usr/bin/perl
use strict;
use warnings;
my $input = '';

print "Input 3: ";
chomp($input = <STDIN>);
print $input."\n";

print "Input 4: ";
chomp($input = <STDIN>);
print $input."\n";

print "Script C finished\n";
 
X

xhoster

spoertsch said:
Hi,

The problem is that script c is not getting the input.

Script A:
#!/usr/bin/perl
use strict;
use warnings;
use IPC::Open2;

my @input = ('test1', 'test2', 'test3', 'test4');
my $out = "";
my $timeout = 7200;
my $RDR;
my $WTR;
my $cmd = 'perl script_b.pl';

my $pid = open2($RDR,$WTR, $cmd) || die("ERROR: Could not execute: " .
$cmd);

foreach (@input){
print $WTR $_."\n";
}

You are cramming all of the output into script_b. Because script_b uses
buffered input, it reads a large chunk of input, essentially being all
of the input intended for both b and c, but processes only the first
two lines. Nothing is left for c to read as it is sitting in b's internal
buffer.

If you make script_a print exactly and only that input expected by
script_b, then issue a read (to get script_bs response), then print the
rest of the data, then it will work. Or make script_b use unbuffered reads
to read only that input that it needs, leaving the rest in the OS-level
buffer where script_c can get it.

Script B:
#!/usr/bin/perl
use strict;
use warnings;
my $input = '';

print "Input 1: ";
chomp($input = <STDIN>);

replace the <STDIN> with:

sysread STDIN, $input, 1, length $input until $input =~ /\n/;
chomp $input;

(may need to adjust /\n/ to reflect whatever line ending you are using.)

Xho

--
-------------------- http://NewsReader.Com/ --------------------
The costs of publication of this article were defrayed in part by the
payment of page charges. This article must therefore be hereby marked
advertisement in accordance with 18 U.S.C. Section 1734 solely to indicate
this fact.
 
J

J. Gleixner

spoertsch said:
Hi,

The problem is that script c is not getting the input. [...]
system('perl script_c.pl');
print "Script B finished\n";

Of course not, you're not passing it anything. Use a similar
open2 that you did in the first script, printing to $WTR,
or pass the arguments on the command line.

I find it odd that you know how to use open2 in one script
and don't have any idea how to use it to pass information,
in the next script.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,768
Messages
2,569,575
Members
45,053
Latest member
billing-software

Latest Threads

Top