如何为Perl系统调用指定超时限制?

Laz*_*zer 27 perl system

有时我的系统调用进入永无止境的状态.为了避免我希望能够在指定的时间后退出呼叫.

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

system("command", "arg1", "arg2", "arg3");
Run Code Online (Sandbox Code Playgroud)

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

dra*_*tun 28

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
}
Run Code Online (Sandbox Code Playgroud)

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
}
Run Code Online (Sandbox Code Playgroud)

  • 这似乎可行,但问题是通过系统调用执行的命令将继续运行,即使父 Perl 进程已经死亡。有谁知道如何获取系统调用运行的进程的进程ID/句柄,以便我们可以在Perl脚本结束之前杀死它? (2认同)

yst*_*sth 14

您可以使用IPC :: Run的run方法而不是system.并设置超时.


Kje*_* S. 5

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

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";
}
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

据我所知,该timeout命令是所有主要“普通”Linux 发行版的一部分,也是 coreutils 的一部分。

  • 我不知道为什么这个答案不更高。对于“运行系统调用时”的上下文,使用系统解决方案似乎很合适,并且简单直接。 (2认同)