Perl如何正确处理系统命令(包括超时和Kill&捕获RC / STDERR / STDOUT)

时间:2014-06-26 11:17:57

标签: perl exec parent-child child-process return-code

从Perl脚本我想执行各种系统命令并在我的脚本中处理输出。

脚本将自动运行,因此我想确保没有命令挂起等。

我愿意接受任何反馈。

我对命令执行的要求:

  • 超时 - >如果命令运行时间超过XX秒,则应该终止其进程
  • 如果命令返回信息,则不必等待超时结束
  • 我想在脚本中捕获退出状态,STDERR,STDOUT。

以下是我从其他stackoverflow问题中得出的一个示例:Kill a hung child process

目前对我不起作用的是:

  • 无法捕获已执行命令的退出状态
  • 无法捕获已执行命令的STDERR

代码:

my $cmd = "sleep 15"; # other tests i use -> "echo bla" and "alkjdsf"
my $TIMEOUT = 10;

my $pid = open my $proc, '-|', "$cmd";

if (fork() == 0) {
    my $poor_mans_alarm = "sleep 1,kill 0,$pid ||exit for 1..$TIMEOUT;kill 9,$pid";
    # run poor man's alarm in a background process
    exec($^X, '-e', "$poor_mans_alarm");
}

my $process_output = "";
while (<$proc>) {
   $process_output .= $_;
}

如果你有这个代码的技巧或推荐一个完全不同的解决方案,请告诉我。

谢谢和欢呼



增加:

使用IPC :: Open3获得了一个工作示例, 但是对于未来的读者,请查看包含超时功能的IPC :: Run, 正如James Green所说。

IPC :: Open3的工作示例:

my $pid = open3(\*WRITE, \*READ,\*ERROR,"$command");

if (fork() == 0) {
    my $poor_mans_alarm = "sleep 1,kill 0,$pid ||exit for 1..10;kill 9,$pid";
    # run poor man's alarm in a background process
    exec($^X, '-e', "$poor_mans_alarm");
}


# get all the STDOUT and STDERR from the Child.
while (<READ>) {
   $output .= $_;
}

while (<ERROR>) {
   $output .= $_;
}

waitpid($pid, 0);
if ($?) {
    $rc = $? >> 8;
    if ($rc != 1){
        print "Some error $?\n";
    }
}

1 个答案:

答案 0 :(得分:0)

看起来IPC::Run几乎提供了你所追求的一切,包括STDOUT和STDERR的超时和捕获。文档位于https://metacpan.org/pod/IPC::Run,包括一些使用示例。