drclaw
drclaw

Reputation: 2483

IPC::Open2 output to already open file handle as per doc example

The documented example in perldoc IPC::Open2 (read from parent STDIN and write to already open handle) is a simplified version of what I'm trying to achieve. Namely, parent writes a preamble to a output file, then a subprocess writes its output directly to the same file.

I've made a simple child script which reads input lines and prints to STDERR and STDOUT. The STDOUT being the the 'already open handle' from the parent.

#!/usr/bin/env perl
##parent.pl
use IPC::Open2;

# read from parent STDIN and write to already open handle
open my $file, '>', 'outfile.txt' or die "open failed: $!";
my $pid = open2($file, "<&STDIN", "./child.pl");

# reap zombie and retrieve exit status
waitpid( $pid, 0 );
my $child_exit_status = $? >> 8;
#!/usr/bin/env perl
##child.pl

while(<STDIN>){
    print STDOUT "STDOUT: ",$_;
    print STDERR "STDERR: ", $_;
}
print STDERR "END OF CHILD\n";

An example run of parent.pl:

Hello
^D
STDERR: Hello
STDERR: END OF CHILD

However, I don't see the expected "STDOUT: Hello" in the output file 'outfile.txt'

Is there some additional setup I've missed to get this example to work?

Upvotes: 3

Views: 552

Answers (1)

user10678532
user10678532

Reputation:

open my $file, '>', 'outfile.txt' or die "open failed: $!";
my $pid = open2($file, "<&STDIN", "./child.pl");

This will create a new pipe, and overwrite the $file variable with a handle refering to the read end of the pipe, closing the old file handle in the process ;-)

In order to pass an existing file handle to open2 or open3, you want to use the >&FILEHANDLE format, but I wasn't able to figure out any way to do that when FILEHANDLE is a local variable, as your my $file.

But the undocumented >&NUM or >&=NUM forms (where NUM is a file descriptor number) just work:

open my $file, '>', 'outfile.txt' or die "open failed: $!";
my $pid = open2('>&'.fileno($file), '<&STDIN', './child.pl');

Example:

$ perl -MIPC::Open2 -e '
   open my $f, ">foo";
   open2(">&".fileno($f), "<&STDIN", "echo bar")
'; cat foo
bar

Upvotes: 4

Related Questions