redirecting stdin/stdout from exec'ed process to pipe in Perl

依然范特西╮ 提交于 2019-12-05 17:36:23

问题


I am trying to have STDOUT/STDERR from a exec'ed child process go back to the parent via a pipe in Perl. The closest I have seen to what I want to do is at : http://forums.devshed.com/perl-programming-6/exec-and-redirecting-stdout-stderr-168501.html

The following is a stripped down example of what I am trying to do. I also tried a variant of the link above. I can't see what I'm doing wrong...

#!/usr/bin/env perl

use strict ;
use warnings ;

my $cmd    = "/usr/bin/who -a" ;  # anything to stdout

pipe( READER, WRITER ) ;
my $child = fork() ;
if ( $child ) {
    print "I am the parent: My pid = $$ junior = $child\n" ;
    close( WRITER ) ;
    my @output = <READER> ;
    print @output ;
    print "parent is DONE\n" ;
} else {
    print "I am the child. My pid = $$\n" ;

    close( READER ) ;
    close( STDOUT );
    close( STDERR );
    *STDOUT = *WRITER ;
    *STDERR = *WRITER ;

    print WRITER "XXX ouput before exec....\n" ;

    exec( $cmd ) or exit(1) ;
}

回答1:


It's not possible to redirect file descriptors just with assignments. Rather one needs to use open like described in perldoc -f open. In your case the child code would look like this:

    print "I am the child. My pid = $$\n" ;

    close( READER ) ;

    open STDOUT, ">&", \*WRITER or die $!;
    open STDERR, ">&", \*WRITER or die $!;

    print WRITER "XXX ouput before exec....\n" ;

    exec( $cmd ) or exit(1) ;



回答2:


Slaven Rezic has the right answer to why your code doesn't work, but you should also be aware of a shortcut that you can use. The special pipe+fork open READER, '-|' does almost all the setup work for you, creating a child process with its STDOUT writing into a pipe that the parent can read with READER. That just leaves the STDERR redirection for you to do manually.

The shortened version of the code looks like this:

my $child = open READER, '-|';
defined $child or die "pipe/fork: $!\n";
if ( $child ) {
    print "I am the parent: My pid = $$ junior = $child\n" ;
    my @output = <READER> ;
    print @output ;
    print "parent is DONE\n" ;
} else {
    print "I am the child. My pid = $$\n" ;

    open STDERR, '>&STDOUT';

    print "XXX ouput before exec....\n" ;

    exec( $cmd ) or exit(1) ;
}



回答3:


This code is another way to pipe the STDOUT and STDERR from the child process.

 #!/usr/bin/env perl
 use strict ;
 use warnings;

 my $cmd    = "/usr/bin/who -a" ;  # anything to stdout

 pipe( READER, WRITER ) ;
 my $child = fork() ;
if ( $child ) {
    print "I am the parent: My pid = $$ junior = $child\n" ;
    close( WRITER ) ;
    my @output = <READER> ;
    print @output ;
    print "parent is DONE\n" ;
} else {
    print "I am the child. My pid = $$\n" ;
    close( READER ) ;
    open(STDERR,">&", WRITER) or die "Cannot duplicate STDERR;
    open(STDOUT,">&", WRITER) or die "cannot duplicate STDOUT";

    print WRITER "XXX ouput before exec....\n" ;

   exec( $cmd ) or exit(1) ;

}



来源:https://stackoverflow.com/questions/18295250/redirecting-stdin-stdout-from-execed-process-to-pipe-in-perl

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!