从子程序执行外部命令(并读取其输出)

时间:2011-09-20 13:23:08

标签: perl

我目前正在修改执行多个shell命令的Perl脚本,对于其中一些命令,捕获输出以进行进一步处理。我想分解在子程序中执行外部命令的代码。我写了以下子程序:

sub execute_command {
  my $cmd = shift;

  Log("executing command $cmd ...");
  system($cmd);
  my $app = ( $? == -1 ) ? $? : $? >> 8;
  if ($app != 0) {
    Log("error executing command $cmd");
    return $FAILURE;
  }
  Log("done");
  return $SUCCESS;
}

sub execute_command_and_get_output {
  my $cmd = shift;

  Log("executing command $cmd ...");
  unless (open( CMD, "$cmd|" )) {
    Log("error executing command $cmd");
    return undef;
  }
  my @cmd = <CMD>;
  close(CMD);
  Log("done");
  return @cmd;    
}

问题:

  1. execute_command应执行传递的命令,如果一切正常,则返回$SUCCESS,如果出现错误,则返回$FAILURE。我是否以正确的方式测试$?

  2. execute_command_and_get_output应执行传递的命令并将输出作为数组返回(包含输出行);如果命令执行失败,则应返回undef。使用unless (open( CMD, "$cmd|" )) { ... }在命令执行中测试错误条件是否正确?

  3. 除了我的两个问题的答案之外,任何改进的建议都表示赞赏。

2 个答案:

答案 0 :(得分:1)

1)如果您不关心发生了什么错误,只需检查system的返回值:

if(system($cmd) == 0) { return $SUCCESS } else { return $FAILURE }

2)仅return undef代替return而不是{{1}}。在列表上下文中调用它时效果更好(它仍然是错误的)。如果返回值很大,您可能希望返回引用以避免复制。

答案 1 :(得分:1)

  • execute_command_and_get_output可以返回两个参数:

    1. $SUCCESS$FAILURE
    2. 对具有结果或为空的数组的引用
  • execute_command也可以返回两个参数:

    1. $SUCCESS$FAILURE
    2. 错误消息。例如:

      system ($cmd) == 0 or return ($FAILURE,"error executing command $cmd: $!");
      return ($SUCCESS, "done");
      
  • 顺便说一下,你可以避免使用反引号通过CMD部分(同样,在多个上下文中使用相同的名称会令人困惑)。

        my @lines = `$cmd`;
        ($? == 0) or return ($FAILURE,"error executing command $cmd: $!");
        return ($SUCCESS, \@lines);