如何从OO Perl中的子进程读取STDOUT

时间:2015-11-10 19:48:10

标签: perl ipc

在Perl中,读取子进程的STDOUT的一种方法是使用open

open(PIPE, "ls -l |");

我正在寻找一种更加面向对象的方式来做到这一点,而且我已经使用IO::Pipe取得了一些成功。我想检测错误,特别是如果命令不可执行。不过,我无法通过IO::Pipe弄清楚如何做到这一点。这就是我所拥有的:

use strict;
use warnings;

use IO::Pipe;


my($cmd) = join (" ", @ARGV);

open(PIPE, "$cmd |") || die qq(error opening PIPE);
while (<PIPE>) {
        chomp;
        print "DBG1: $_\n";
}

close PIPE;

my($pipe) = IO::Pipe->new();
$pipe->reader($cmd);
die qq(error opening IO::Pipe) if $pipe->eof();

while (<$pipe>) {
        chomp;
        print "DBG2: $_\n";
}

$pipe->close();

如果子流程命令无效,则两个检查都将正确die。但是,如果子进程没有产生输出,eof()将报告错误,即使命令本身没问题:

$ perl pipe.pl "ls -l >/dev/null"
error opening IO::Pipe at pipe.pl line 20.

然后是一堆问题:

是否有合理的OO方式从Perl中的子进程读取? IO::Pipe是否使用正确的工具?如果是这样,我如何检查以确保成功创建子流程命令?如果没有,我应该使用什么?我不想写这个子流程,所以我不认为我想要IPC::Open2IPC::Open3。如果可能的话,我更愿意使用核心模块。

2 个答案:

答案 0 :(得分:3)

问题不在于IO :: Pipe。问题是eof是检查管道错误的错误方法。这并不意味着没有管道,这意味着没有什么可以从该管道读取。你对eof PIPE也有同样的问题。子流程不打印任何东西都是完美的。

如果你想检查子流程是否成功运行,事实证明IO :: Pipe已经为你做了。

# IO::Pipe: Cannot exec: No such file or directory
$pipe->reader("hajlalglagl");

答案 1 :(得分:0)

Backticks不是核心模块,但似乎可以满足您的需求。

use strict;
use warnings;
use Backticks;
my $cmd = Backticks->new(join (" ", @ARGV));
$cmd->run();

if ($cmd->success){
        print $cmd->stdout
} else {
        print "Command failed\n";
}

使用有效命令运行此命令然后无效命令将给出以下结果

io_pipe.pl“uname -o”

GNU/Linux

io_pipe.pl“uname -z”

Command failed

<强>更新 正如@thisSuitIsNotBlack所指出的,这个模块改变了pe​​rl中反引号的嘲讽行为。您应该阅读POD的Notes部分。然而,要注意的主要是:

  

backticks的覆盖由Filter :: Simple提供。资源   有时过滤可能很奇怪...如果你想使用这个模块   纯粹传统的Perl OO风格,只需关闭源代码即可   加载模块后立即过滤:

 use Backticks;
 no Backticks;