在Perl中将执行的进程的标准输入/输出重定向到管道

14
我尝试在Perl中通过管道将exec的子进程的标准输出/标准错误返回给父进程。我看到的最接近我想做的是这个链接: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) ;
}

2
你可能会对IPC::Open2感兴趣。 - squiguy
3个回答

8

仅靠赋值是无法重定向文件描述符的。相反,需要像perldoc -f open中所述那样使用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) ;

7
Slaven Rezic已经回答了你的代码为什么不起作用,但你还应该知道一个快捷方式。特殊的管道+分叉open 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) ;
}

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) ;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接