【问题标题】:How to read STDOUT from a sub-process in OO Perl如何从 OO Perl 中的子进程读取 STDOUT
【发布时间】:2016-02-11 19:42:43
【问题描述】:

在 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。如果可能的话,我更喜欢使用核心模块。

【问题讨论】:

    标签: perl ipc


    【解决方案1】:

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

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

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

    【讨论】:

      【解决方案2】:

      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 的注释部分。但是要注意的主要一点是:

      backticks 的覆盖由 Filter::Simple 提供。资源 过滤有时会很奇怪......如果你想在 纯粹传统的 Perl OO 风格,干脆关掉源码 加载模块后立即过滤:

       use Backticks;
       no Backticks;
      

      【讨论】:

      • 默认情况下,反引号使用source filtering 覆盖`` 的行为。我会禁用这个,因为source filters are generally bad。文档推荐 use Backticks; no Backticks;,尽管我仍在尝试了解它是如何工作的。
      • @ThisSuitIsBlackNot - 是的,我注意到在 POD 和恢复 perl 反引号功能的各种方法中,但留给用户自己阅读 POD。我假设如果他想使用更面向对象的方法来调用外部命令,他会为所有人这样做
      • 我的意思是,您的示例代码改变了核心运算符的行为,但没有任何迹象表明它会这样做。我认为这值得在您的答案文本(或代码本身)中提及,而不是隐藏在链接中。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-11
      • 1970-01-01
      • 2016-12-21
      • 2020-06-23
      • 1970-01-01
      • 2011-11-12
      相关资源
      最近更新 更多