2016-06-15 3 views
2

Я программирую скрипт perl для мониторинга базы данных с Nagios. Я использую функцию будильника из библиотеки Time :: HiRes для таймаута.Выходное сообщение Perl TIMEOUT

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

Все работает нормально. Дело в том, что я хочу, чтобы изменить выходное сообщение потому что это возвращает «Temporizador» и если я делаю

echo $? 

Возврат 142. Я хочу, чтобы изменить сообщение для того, чтобы сделать «выход 3», поэтому он может быть признанный Nagios.

Уже пробовал 'eval', но не работает.

+2

'Temporizador' выводится вашей оболочкой, когда один из его детей убит сигналом ARLM. '$?' здесь не является кодом выхода ребенка; это номер сигнала, который убил ребенка (14) ORed с 128. – ikegami

ответ

3

Функция, использующая время, записывается на C, что исключает возможность безопасного использования специального обработчика сигналов.

Вы не беспокоитесь о том, чтобы принудительно завершить свою программу, поэтому я предлагаю вам использовать alarm без обработчика сигнала, чтобы принудительно завершить работу вашей программы, если она слишком долго запускается, и используя обертку для обеспечения правильного ответа на Nagios ,

Изменить

/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.

3

Вы должны обработать сигнал 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:[email protected]:~/$ ./test.pl 
Custom message 
18:08:[email protected]:~/$ echo $? 
3 

Для расширенного объяснения об обработке сигналов проверки this nice tutorial on perltricks.

+0

Он работает. У меня есть вопрос. Зачем спать? Я проверил, не поставил ли я спать 10 значение тревоги не может быть больше 10. Почему? –

+0

Это только для примера. «Сон» должен быть больше, чем «будильник». В противном случае программа закончится и сигнал 'ALRM' не будет принят. – eballes

+4

@Adrian Blanco, 'sleep' представляет остальную часть вашей программы. На самом деле не используйте 'sleep'. – ikegami

Смежные вопросы