IPC::Open3 有问题

Trouble with IPC::Open3

我正在使用 IPC::Open3 编写一个简单的脚本。该脚本不会向 stdout 或 stderr 产生任何输出,而我希望两者都有输出。

完整源码:

#!/usr/bin/env perl 

use strict;
use warnings;
use utf8;

use IPC::Open3;

pipe my $input, my $output or die $!;
my $pid =  open3(\*STDIN, $output, \*STDERR, 'dd', 'if=/usr/include/unistd.h') or die $!;

while(<$input>) {
    print $_."\n";
}
waitpid $pid, 0;

我很确定我使用 IPC::Open3 不正确。然而,我仍然对我应该做什么感到困惑。

pipe。不知道为什么它在那里我不能说更多。这很好用。

my $reader;
my $pid =  open3(\*STDIN, $reader, \*STDERR, 'dd', 'if=/usr/include/unistd.h') or die $!;

while(<$reader>) {
    print $_."\n";
}
waitpid $pid, 0;

我知道这 可能 只是一个例子,但万一它不是......这对你正在做的事情来说完全是矫枉过正。你可以用反引号来完成。

print `dd if=/usr/include/unistd.h`

IPC::Open3 有点过于复杂。还有更好的模块比如IPC::Run and IPC::Run3.

use strict;
use warnings;

use IPC::Run3;

run3(['perl', '-e', 'warn "Warning!"; print "Normal\n";'],
     \*STDIN, \*STDOUT, \*STDERR
);

您的程序存在以下问题:

  • \*STDIN(打开 STDIN 作为连接到 child 的 STDIN 的管道)应该是 <&STDIN(使用 parent 的 STDIN 作为 child 的 STDIN).
  • \*STDERR(打开 STDERR 作为连接到 child 的 STDERR 的管道)应该是 >&STDERR(使用 parent 的 STDERR 作为 child 的 STDERR).
  • 您在 $output 中设置的值将被忽略和覆盖。幸运的是,它正在被正确的值覆盖!
  • 您使用 print $_."\n";,但 $_ 已经是 newline-terminated。要么先 chomp,要么不添加换行符。
  • open3 不是系统调用,因此不会设置 $!.
  • open3 不会在错误时 return false;它抛出异常。

所以我们得到类似的东西:

#!/usr/bin/env perl

use strict;
use warnings;
use feature qw( say );

use IPC::Open3;

my $pid = open3('<&STDIN', my $output, '>&STDERR',
    'dd', 'if=/usr/include/unistd.h');

while (<$output>) {
    chomp;
    say "<$_>";
}

waitpid($pid, 0);