【问题标题】:Trouble with IPC::Open3IPC::Open3 的问题
【发布时间】:2017-02-18 07:01:59
【问题描述】:

我正在使用 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 的目的是什么?
  • 不知道,应该没了。

标签: perl ipc


【解决方案1】:

这是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::RunIPC::Run3

use strict;
use warnings;

use IPC::Run3;

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

【讨论】:

  • 我仍然没有得到 stderr 输出,即使我使用了将某些内容重定向到 stderr 的 shell 命令。
  • @Demi open3() 很难使用。我用更好的模块扩展了答案。
【解决方案2】:

您的程序存在以下问题:

  • \*STDIN(打开STDIN作为连接到孩子STDIN的管道)应该是&lt;&amp;STDIN(使用父母的STDIN作为孩子的STDIN)。
  • \*STDERR(打开STDERR作为连接到孩子STDERR的管道)应该是&gt;&amp;STDERR(使用父母的STDERR作为孩子的STDERR)。
  • 您在$output 中放置的值将被忽略和覆盖。幸运的是,它被正确的值覆盖了!
  • 您使用print $_."\n";,但$_ 已经换行终止。先chomp,或者不添加换行符。
  • open3 不是系统调用,所以它没有设置$!
  • open3 出错时不返回 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);

【讨论】:

  • 这会关闭 STDIN,这是我不想要的,但我可以通过几个 open 调用来复制文件描述符来解决这个问题。谢谢!
  • 我认为open(local *CHILD_STDIN, '&lt;&amp;', \*STDIN) or die $!;'&lt;&amp;CHILD_STDIN' 可以,但如果不复制输入句柄,您可能会遇到问题。
猜你喜欢
  • 2014-07-09
  • 2012-08-17
  • 1970-01-01
  • 2012-04-19
  • 1970-01-01
  • 2011-01-07
  • 2013-12-22
  • 1970-01-01
  • 2011-03-01
相关资源
最近更新 更多