从exec'重定向stdin/stdout;Perl中的管道化进程

从exec'重定向stdin/stdout;Perl中的管道化进程,perl,redirect,exec,pipe,stdout,Perl,Redirect,Exec,Pipe,Stdout,我试图让执行子进程中的STDOUT/STDERR通过Perl中的管道返回到父进程。我所看到的最接近我想做的事情是: 下面是我试图做的一个简单的例子。我还尝试了上面链接的变体。我看不出我做错了什么 #!/usr/bin/env perl use strict ; use warnings ; my $cmd = "/usr/bin/who -a" ; # anything to stdout pipe( READER, WRITER ) ; my $child = fork() ;

我试图让执行子进程中的STDOUT/STDERR通过Perl中的管道返回到父进程。我所看到的最接近我想做的事情是:

下面是我试图做的一个简单的例子。我还尝试了上面链接的变体。我看不出我做错了什么

#!/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) ;
}
#/usr/bin/env perl
严格使用;
使用警告;
my$cmd=“/usr/bin/who-a”#有什么要说的吗
管道(读写器);
我的$child=fork();
if(儿童){
打印“我是家长:我的pid=$$junior=$child\n”;
关闭(作者);
我的@output=;
打印@输出;
打印“父项已完成\n”;
}否则{
打印“我是孩子。我的pid=$$\n”;
关闭(读卡器);
关闭(标准输出);
关闭(STDERR);
*STDOUT=*WRITER;
*STDERR=*编写器;
打印写入程序“执行前输出XXX…”\n;
exec($cmd)或exit(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) ;
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) ;
}

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

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

    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) ;
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) ;
}
my$child=openreader'-|';
定义$child或die“管道/叉:$!\n”;
if(儿童){
打印“我是家长:我的pid=$$junior=$child\n”;
我的@output=;
打印@输出;
打印“父项已完成\n”;
}否则{
打印“我是孩子。我的pid=$$\n”;
打开STDERR,'>&STDOUT';
打印“执行前输出XXX…”\n;
exec($cmd)或exit(1);
}

此代码是另一种通过管道将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) ;
#/usr/bin/env perl
严格使用;
使用警告;
my$cmd=“/usr/bin/who-a”#有什么要说的吗
管道(读写器);
我的$child=fork();
if(儿童){
打印“我是家长:我的pid=$$junior=$child\n”;
关闭(作者);
我的@output=;
打印@输出;
打印“父项已完成\n”;
}否则{
打印“我是孩子。我的pid=$$\n”;
关闭(读卡器);
打开(STDERR,“>&”,WRITER)或死“不能复制STDERR;
打开(标准输出“>&”,写入器)或死亡“无法复制标准输出”;
打印写入程序“执行前输出XXX…”\n;
exec($cmd)或exit(1);
}

您可能会感兴趣。