为分叉进程重新分配STDOUT

时间:2014-09-01 06:04:25

标签: perl

我正在尝试将分叉进程的STDOUT分配给管道。例如

use warnings;
use strict;
use feature qw(say);
use IO::Select;

my $cmd='sleep 2; echo Hello';
pipe(PREAD, PWRITE);

my $pid=fork();
if ($pid==0) {
  *STDOUT=*PWRITE;
  exec $cmd;
  die "Could not run command \"$cmd\"";
}
my $sel = IO::Select->new( \*PREAD );
say "Waiting for background process..";
while (1) {
  my @ready = $sel->can_read;
  last if (! @ready);
  for my $fh (@ready) {
    say "Processing file descriptor ".($fh->fileno());
    my $line=<$fh>;
    if (! defined $line) {
      say "EOF";
      $sel->remove($fh);
      next;
    }
    chomp($line);
    say "Got line: \"$line\"..";
  }
}
waitpid ($pid,0);
say "Done.";

但管道PREAD中没有出现任何内容;孩子仍然输出到STDOUT而不是管道。

1 个答案:

答案 0 :(得分:2)

  

* STDOUT = * PWRITE;

这只会将perl文件句柄PWRITE分配给perl文件句柄STDOUT,但不会更改操作系统的基础文件描述符。为此,您需要将基础文件描述符从PWRITE复制到fd 1(STDOUT):

开(STDOUT,&#34;&GT;&安培; PWRITE&#34);

在您执行此操作后,PWRITE会重复,现在可以作为PWRITE和STDOUT访问。一个好的风格是close(PWRITE)然后使STDOUT成为写入管道的唯一文件句柄。