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

How to read STDOUT from a sub-process in OO Perl

在 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.

一堆问题,然后:

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

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 所指出的,此模块更改了 perl 中反引号的默认行为。您应该阅读 POD 的注释部分。然而,要注意的主要问题是:

The overriding of backticks is provided by Filter::Simple. Source filtering can be weird sometimes... if you want to use this module in a purely traditional Perl OO style, simply turn off the source filtering as soon as you load the module:

 use Backticks;
 no Backticks;

问题不是 IO::Pipe。问题是 eof 是检查管道错误的错误方法。这并不意味着没有管道,这意味着没有任何东西可以从那个管道读取eof PIPE 也会有同样的问题。子进程不打印任何东西是完全没问题的。

如果您想成功检查子流程 运行,结果 IO::Pipe 已经为您完成了。

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