12

我试图让执行的子进程中的 STDOUT/STDERR 通过 Perl 中的管道返回父进程。我所看到的最接近我想做的是: http ://forums.devshed.com/perl-programming-6/exec-and-redirecting-stdout-stderr-168501.html

以下是我正在尝试做的一个精简示例。我还尝试了上面链接的变体。我看不出我做错了什么...

#!/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) ;
}
4

3 回答 3

7

仅通过分配来重定向文件描述符是不可能的。而是需要open像中描述的那样使用perldoc -f open。在您的情况下,子代码如下所示:

    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) ;
于 2013-08-18T09:59:22.773 回答
6

Slaven Rezic 对为什么您的代码不起作用有正确的答案,但您也应该知道可以使用的快捷方式。特殊的 pipe+forkopen READER, '-|'为您完成了几乎所有的设置工作,创建了一个子进程并将其STDOUT写入到父进程可以读取的管道中READER。这只是让STDERR您手动进行重定向。

代码的缩短版本如下所示:

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) ;
}
于 2013-08-18T13:45:53.783 回答
0

此代码是从子进程通过管道传输 STDOUT 和 STDERR 的另一种方法。

 #!/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) ;
}
于 2017-06-26T15:26:26.737 回答