如何从 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::Open2
或IPC::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");
在 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::Open2
或IPC::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");