代码之家  ›  专栏  ›  技术社区  ›  Mike

perl,重定向stdout,但保持父级

  •  3
  • Mike  · 技术社区  · 14 年前

    在Perl之后 fork() 我可以将孩子的stdout重定向到这样的文件

    open STDOUT,">",$filename or die $!
    

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

    2 回复  |  直到 14 年前
        1
  •  3
  •   Greg Bacon    14 年前

    在孩子身上,执行

    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
        2
  •  0
  •   Sean    14 年前

    如果父级可以等待子级完成,则子级可以将其输出返回父级,父级负责将其打印到stdout和目标文件:

    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;
    

    事实上,即使家长不能等待孩子完成任务,如果家长首先将一个子分叉来执行上面概述的逻辑,这个策略仍然有效。