【问题标题】:Perl TIMEOUT output messagePerl 超时输出消息
【发布时间】:2016-06-15 16:01:47
【问题描述】:

我正在编写一个 perl 脚本来使用 Nagios 监控数据库。 我正在使用 Time::HiRes 库中的警报功能进行超时。

use Time::HiRes qw[ time alarm ];
alarm $timeout;

一切正常。问题是我想更改输出消息,因为它返回“Temporizador”,如果我这样做了

echo $?

返回 142。我想更改消息以创建“退出 3”,以便 Nagios 能够识别它。

已经尝试过 'eval' 但不起作用。

【问题讨论】:

  • Temporizador 由您的外壳输出,当它的一个孩子被 ARLM 信号杀死时。 $?这里不是孩子的退出代码;它是杀死孩子的信号编号 (14) 与 128 相或。

标签: perl timeout output alarm nagios


【解决方案1】:

花费时间的函数是用 C 编写的,这使您无法安全地使用自定义信号处理程序。

您似乎并不担心强制终止您的程序,因此我建议您使用不带信号处理程序的alarm 来强制终止您的程序(如果运行时间过长),并使用包装器来提供正确的响应纳吉奥斯。

改变

/path/to/program some args

/path/to/timeout_wrapper 30 /path/to/program some args

以下是timeout_wrapper

#!/usr/bin/perl
use strict;
use warnings;

use POSIX       qw( WNOHANG );
use Time::HiRes qw( sleep time );

sub wait_for_child_to_complete {
   my ($pid, $timeout) = @_;
   my $wait_until = time + $timeout;
   while (time < $wait_until) {
      waitpid($pid, WNOHANG)
         and return $?;

      sleep(0.5);
   }

   return undef;
}

{
   my $timeout = shift(@ARGV);

   defined( my $pid = fork() )
      or exit(3);

   if (!$pid) {
      alarm($timeout);   # Optional. The parent will handle this anyway.
      exec(@ARGV)
         or exit(3);
   }

   my $timed_out = 0;
   my $rv = wait_for_child_to_complete($pid, $timeout);
   if (!defined($rv)) {
      $timed_out = 1;
      if (kill(ALRM => $pid)) {
         $rv = wait_for_child_to_complete($pid, 5);
         if (!defined($rv)) {
            kill(KILL => $pid)
         }
      }
   }

   exit(2) if $timed_out;
   exit(3) if $rv & 0x7F;  # Killed by some signal.
   exit($rv >> 8);         # Expect the exit code to comply with the spec.
}

使用Nagios Plugin Return Codes。超时实际上应该返回2

【讨论】:

    【解决方案2】:

    您应该处理ALRM 信号。例如:

    #!/usr/bin/env perl
    use strict;
    use warnings;
    use Time::HiRes qw[ time alarm ];
    
    $SIG{ALRM} = sub {print "Custom message\n"; exit 3};
    
    alarm 2;
    sleep 10; # this line represents the rest of your program, don't include it
    

    这将输出:

    18:08:20-eballes@urth:~/$ ./test.pl 
    Custom message
    18:08:23-eballes@urth:~/$ echo $?
    3
    

    有关处理信号的详细说明,请查看this nice tutorial on perltricks

    【讨论】:

    • 它正在工作。我有个问题。为什么要睡觉?我检查了如果我把 sleep 10 警报值不能大于 10。为什么?
    • 这只是示例。 sleep 需要大于 alarm。否则程序结束,不会收到ALRM 信号。
    • @Adrian Blanco, sleep 代表你程序的其余部分。实际上不要使用sleep
    • @Adrian Blanco,您要中断的函数是用 C 编写的吗?那不会发生。您不能安全地中断对 C 函数的调用(例如,正则表达式匹配、XS 函数)。仍应调用处理程序,但将在例程退出后调用它。但是,您听起来好像根本没有调用处理程序。如果是这样,要么程序运行的时间不够长,无法触发警报,要么正在清除警报(例如,通过使用 alarm 本身)或警报处理程序(不太可能)。
    • @Adrian Blanco,是的,这就是问题所在。它的核心是一个 C 函数。我会尽快发布解决方案。
    猜你喜欢
    • 2013-05-27
    • 1970-01-01
    • 2011-01-24
    • 2013-03-08
    • 1970-01-01
    • 2013-02-26
    • 1970-01-01
    • 2021-03-19
    • 2020-05-28
    相关资源
    最近更新 更多