管道文件句柄到自己的叉子

时间:2013-02-15 07:31:30

标签: perl

我知道我可以做到以下几点:

open(STDOUT, "|-", "cmd");

这可能导致以下结果:

  1. fork();
  2. exec("cmd");
  3. 将原始流程的STDOUT链接到新流程的STDIN。
  4. 我想做的是上面的第2步,即不要exec()。只需要继续当前进程的两个副本,子进程的STDIN链接到父进程的STDOUT。

    这将允许我继续这样:

    if (! $pid)
    {
      # Handle data in child here
      open OUTFILE1 $file1;
      open OUTFILE2 $file2;
      my $i = 0;
      while (<>)
      {
        print (i % 2 ? OUTFILE1 : OUTFILE2) "Line $i: $_";
        ++$i;
      }
      exit;
    }
    else
    {
      # Continue parent here
      print STDOUT "Hello World from print()";
      system("echo Hello World from system()");
    }
    

    上面的代码应该在输出中添加一个行号,并逐行地将这些数据写入不同的文件(我知道它有点傻,但它只是一个例子)。

    有没有办法或图书馆这样做?我考虑过perltie,但它似乎没有处理来自system()的结果,因此我认为我需要一个单独的流程来实际管道STDOUT。

1 个答案:

答案 0 :(得分:3)

IIRC,你只想要

open(STDOUT, "|-", "-");

open3也只需要一行,有更好的错误报告,并且还允许您捕获STDERR。

use IPC::Open3 qw( open3 );
use POSIX      qw( _exit );

sub child {
   print("Hello World from print()\n");
   system("echo", "Hello World from system()");
}

my $pid = open3(
   '<&STDIN',
   \local *CHILD_STDOUT,
   '>&STDERR',
   '-',
);

if (!$pid) {
   if (eval { child(); 1 }) {
      _exit(0);
   } else {
      print(STDERR $@);
      _exit($! || ($? >> 8) || 255);
   }
}

while (<CHILD_STDOUT>) {
   ...
}

waitpid($pid, 0);