【问题标题】:How can I specify timeout limit for Perl system call?如何为 Perl 系统调用指定超时限制?
【发布时间】:2011-04-27 10:01:45
【问题描述】:

有时我的系统调用会进入永无止境的状态。为了避免我希望能够在指定的时间后中断通话。

有没有办法为system指定超时限制?

system("command", "arg1", "arg2", "arg3");

我希望从 Perl 代码中实现超时以实现可移植性,而不是使用某些特定于操作系统的函数,例如 ulimit。

【问题讨论】:

标签: perl system


【解决方案1】:

请参阅alarm 函数。来自 pod 的示例:

eval {
    local $SIG{ALRM} = sub { die "alarm\n" }; # NB: \n required
    alarm $timeout;
    $nread = sysread SOCKET, $buffer, $size;
    alarm 0;
};
if ($@) {
    die unless $@ eq "alarm\n";   # propagate unexpected errors
    # timed out
}
else {
    # didn't
}

CPAN 上有一些模块可以更好地包装这些模块,例如:Time::Out

use Time::Out qw(timeout) ;

timeout $nb_secs => sub {
  # your code goes were and will be interrupted if it runs
  # for more than $nb_secs seconds.
};

if ($@){
  # operation timed-out
}

【讨论】:

  • 这似乎可行,但问题是通过系统调用执行的命令将继续运行,即使父 Perl 进程已经死亡。有谁知道如何获取系统调用运行的进程的进程ID/句柄,以便我们可以在Perl脚本结束之前杀死它?
  • @antred - 要获取进程 ID,您需要使用 fork 而不是 system 重写它。查看 IPC::Cmd 和 IPC::Run 之类的模块以使这更容易(在这种情况下)。
【解决方案2】:

你可以使用IPC::Run的run方法代替system。并设置超时。

【讨论】:

    【解决方案3】:

    System::Timeout 怎么样?

    此模块扩展 system 以允许在指定秒数后超时。

    timeout("3", "sleep 9"); # timeout exit after 3 seconds
    

    【讨论】:

    • 仅链接的答案在内容移动或更改时没有帮助。在您的回答中包含链接的相关部分,根据问题量身定制。
    • 始终欢迎提供指向潜在解决方案的链接,但请add context around the link,以便您的其他用户知道它是什么以及为什么存在。始终引用重要链接中最相关的部分,以防目标站点无法访问或永久离线。考虑到仅仅是指向外部站点的链接是Why and how are some answers deleted? 的一个可能原因。
    【解决方案4】:

    我之前在 Perl + Linux 中使用过timeout 命令,你可以这样测试:

    for(0..4){
      my $command="sleep $_";  #your command
      print "$command, ";
      system("timeout 1.1s $command");  # kill after 1.1 seconds
      if   ($? == -1  ){ printf "failed to execute: $!" }
      elsif($?&127    ){ printf "died, signal %d, %scoredump", $?&127, $?&128?'':'no '}
      elsif($?>>8==124){ printf "timed out" }
      else             { printf "child finished, exit value %d", $? >> 8 }
      print "\n";
    }
    

    4.317 秒后的输出:

    sleep 0, child finished, exit value 0
    sleep 1, child finished, exit value 0
    sleep 2, timed out
    sleep 3, timed out
    sleep 4, timed out
    

    timeout 命令是所有主要“正常”Linux 发行版 a.f.a.i.k 的一部分,也是 coreutils 的一部分。

    【讨论】:

    • 我不知道为什么这个答案不高。对于“运行系统调用时”的上下文,使用系统解决方案似乎很合适,而且简单直接。
    • 非常适合“作为胶水代码的 perl”。谢谢。下次我编写 perl 应用程序时,IPC::Run 将开始运行,但无论如何,当我在炮击时,这是正确的。
    猜你喜欢
    • 1970-01-01
    • 2015-02-19
    • 2016-04-10
    • 2013-05-30
    • 1970-01-01
    • 2017-10-10
    • 2014-08-10
    • 2012-10-12
    • 1970-01-01
    相关资源
    最近更新 更多