在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::Open2
或IPC::Open3
。如果可能的话,我更愿意使用核心模块。
答案 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所指出的,这个模块改变了perl中反引号的嘲讽行为。您应该阅读POD的Notes部分。然而,要注意的主要是:
backticks
的覆盖由Filter :: Simple提供。资源 有时过滤可能很奇怪...如果你想使用这个模块 纯粹传统的Perl OO风格,只需关闭源代码即可 加载模块后立即过滤:
use Backticks;
no Backticks;