【问题标题】:redirecting stdin/stdout from exec'ed process to pipe in Perl将标准输入/标准输出从执行的进程重定向到 Perl 中的管道
【发布时间】:2013-08-20 03:43:03
【问题描述】:

我试图让已执行子进程中的 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) ;
}

【问题讨论】:

标签: perl redirect exec pipe stdout


【解决方案1】:

仅通过赋值来重定向文件描述符是不可能的。而是需要使用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) ;

【讨论】:

    【解决方案2】:

    Slaven Rezic 对您的代码为什么不起作用有正确的答案,但您也应该知道可以使用的快捷方式。特殊的 pipe+fork 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) ;
    }
    

    【讨论】:

      【解决方案3】:

      此代码是从子进程通过管道传输 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) ;
      }
      

      【讨论】:

        猜你喜欢
        • 2013-07-16
        • 2016-04-26
        • 1970-01-01
        • 2012-03-13
        • 1970-01-01
        • 1970-01-01
        • 2019-03-17
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多