Perl,重定向stdout,但保持在父级

Perl,重定向stdout,但保持在父级,perl,io-redirection,tee,Perl,Io Redirection,Tee,在perl中,在fork()ing之后,我可以将孩子的stdout重定向到如下文件 open STDOUT,">",$filename or die $! 我想知道是否有一种“复制它”的方法,将stdout保留在父级的stdout上,同时也复制到指定的文件。它应该以不需要任何缓冲的方式发生,并且用户可以实时看到控制台输出。这有点像unixtee。但理想情况下,解决方案不会涉及任何第三方库。在子级中,执行 open STDOUT, "|-", "tee", $output or die

在perl中,在
fork()
ing之后,我可以将孩子的stdout重定向到如下文件

open STDOUT,">",$filename or die $!
我想知道是否有一种“复制它”的方法,将stdout保留在父级的stdout上,同时也复制到指定的文件。它应该以不需要任何缓冲的方式发生,并且用户可以实时看到控制台输出。这有点像unix
tee
。但理想情况下,解决方案不会涉及任何第三方库。

在子级中,执行

open STDOUT, "|-", "tee", $output
  or die "$0: failed to start tee: $!";
如果出于某种原因您不想使用
tee
,您可以使用穷人版本,方法是通过
open STDOUT“|-”
将另一个孩子交给另一个孩子,然后在孙辈中进行复制:

#! /usr/bin/perl

use warnings;
use strict;

my $pid = fork;
die "$0: fork: $!" unless defined $pid;

if ($pid) {
  waitpid $pid, 0;
}
else {
  my $pid = open STDOUT, "|-";
  die "$0: fork: $!" unless defined $pid;
  select STDOUT; $| = 1;  # disable STDOUT buffering
  if ($pid) {
    print "Hiya!\n";
    system "echo Howdy";
    close STDOUT or warn "$0: close: $!";
    exit 0;
  }
  else {
    open my $fh, ">", "/tmp/other-output" or die "$0: open: $!";
    my $status;
    while ($status = sysread STDIN, my $data, 8192) {
      syswrite $fh, $data and print $data or die "$0: output failed: $!";
    }
    die "$0: sysread: $!" unless defined $status;
    close $fh or warn "$0: close: $!";
    exit 0;
  }
}
样本运行:

$ ./owntee Hiya! Howdy $ cat other-output Hiya! Howdy 美元/业主 你好! 你好 $cat其他输出 你好!
Howdy如果父级可以等待子级完成,子级可以通过管道将其输出返回给父级,父级负责将其打印到标准输出和目标文件:

open my $destfile, '>', $path or die "Can't open destination file: $!\n";

my $pid = open my $child, '-|';
defined $pid or die "Can't fork: $!\n";

if ($pid == 0) {
    # Child process:
    print "I'm the child!\n";
    close $destfile;
    #  do whatever
    exit;
}

# Parent process:

while (<$child>) {
    print STDOUT    $_;
    print $destfile $_;
}

close $child;
close $destfile;
打开我的$destfile,'>',$path或die“无法打开目标文件:$!\n”;
my$pid=打开我的$child,'-|';
定义了$pid或die“无法分叉:$!\n”;
如果($pid==0){
#子进程:
打印“我是孩子!\n”;
关闭$dest文件;
#做任何事
出口
}
#父进程:
而(){
打印标准输出$;
打印$destfile$;
}
关闭$child;
关闭$dest文件;

实际上,即使家长不能等待孩子完成,如果家长首先让孩子执行上述逻辑,这种策略仍然有效。

您提到的“理想”解决方案不会涉及任何第三方库,但为了子孙后代,IO::Tee就是为了解决这个问题而编写的,而且做得非常好。我认为应该有一种使用内置文件IO的简单方法