2015-01-25 3 views
0

У меня есть сценарий bash (который я конвертирую в perl), который работает в бесконечном цикле (while true; do) для опроса устройств в нашей сети и регистрации их ответов на текстовый файл , С каждой итерацией цикла (while) текстовый файл для этого устройства добавляется с его последней информацией.Watchdog-подобная поддержка (bash perl или python)

Я бы хотел, чтобы этот скрипт всегда запускался - если он зависает, сбой или больше не записывается в соответствующие текстовые файлы, его следует перезапустить.

Следуя советы, публикуемых в this StackOverflow вопроса, я мог бы написать следующий Баш скрипт:

until myserver; do 
    echo "Server 'myserver' crashed with exit code $?. Respawning.." >&2 
    sleep 1 
done 

где myserver является программой опроса. Это будет учитывать проблемы с неожиданным сбоем или зависанием сценария, предполагая, что в этих случаях был выпущен ненулевой код выхода. Однако, если сценарий не полностью завершает работу/завершает работу, но выходит из строя таким образом, что он просто перестает писать текстовые файлы - я тоже хотел бы перезапустить скрипт. Вот где бы появился скрипт, похожий на сторожевой. Я мог использовать Python watchdog и написать сценарий, который использует библиотеку Observer для отслеживания генерируемых текстовых файлов, like in this example. Я хотел бы вызвать на застойных текстовые файлы выдать ненулевой выход для сценария питона, а затем дополнить вышеуказанный Баш скрипт следующим образом:

until [myserver -o pythonMon]; do 
    echo "Server 'myserver' crashed with exit code $?. Respawning.." >&2 
    sleep 1 
done 

где pythonMon является сценарием питона мониторинга или не обновляют текстовые файлы должным образом. К сожалению, для этого подхода требуются три сценария (основной сценарий опроса и два сценария мониторинга); это немного клочья. Я ищу для оптимизации/упрощения этого подхода. Любые рекомендации? В идеале у меня был бы один скрипт (по крайней мере один сценарий мониторинга), чтобы поддерживать скрипт опроса против двух. Будет ли способ добавить мониторинг файлов непосредственно в bash или perl-код? Это работает на 64-разрядной версии, CentOS 6.5

+1

Я предполагаю, что между опросами есть какая-то пауза. Как насчет того, чтобы вырезать цикл из вашей программы, чтобы он только один раз запрашивал оборудование, записывал результат и выходил.Затем вы можете запустить его как задание «cron», которое будет работать с одинаковой частотой, и вопрос о перезапуске не возникает. Все, что происходит, если опрос проваливается, состоит в том, что в последовательности данных отсутствует запись. – Borodin

+0

@Borodin есть пауза, но опрос происходит каждые 10 секунд, поэтому задание cron не будет работать, так как он разрешает выполнение скрипта один раз в минуту (требуется 10 секунд). – secJ

+1

Тогда ваша программа Perl должна «развить» дочерний процесс Perl каждые десять секунд, и пусть это сделает опрос. Родительский процесс может «убить» и собрать последний ребенок до появления нового, хотя ваше требование перезапустить * «если [процесс] больше не записывается в соответствующие текстовые файлы» *, это немного беспокоит. Какую ошибку вы представляете здесь, и как ее можно протестировать? Я бы написал ответ с некоторым примером кода, но сейчас я использую планшет и ничего не могу проверить. – Borodin

ответ

1

Я делаю что-то довольно похожее для мониторинга множества устройств. Зависит немного от частоты опроса, хотя - я нерестую через cron с интервалом 3 м.

Помните, что образцы 10 с потенциально достаточно интенсивными и могут не всегда быть необходимыми - это немного зависит от того, к чему вы стремитесь.

Во всяком случае, инструмент для работы Parallel :: ForkManager.

#!/usr/bin/perl 

use strict; 
use warnings; 

use Parallel::ForkManager; 

my @targets = qw(server1 server2); 

my %test_list = { 'fetch_cpu' => \&fetch_cpu_stats, }; 


sub fetch_cpu_stats { 
    my ($target) = @_; 
    ## do something to $target; 
    open(my $ssh_results, "-|", "ssh -n $target uptime") 
     or die $!; 
    while (<$ssh_results>) { 
     print; 
    } 
} 

my $manager = Parallel::ForkManager->new(10); 

while (1) { 
    foreach my $test (keys %test_list) { 
     foreach my $target (@targets) { 
      $manager->start and next; 
      print "$$ starting $test\n"; 
      &{$test_list{$test}}($target); 
      $manager -> finish; 
     } 
    } 
    sleep 10; 
} 

Это будет порождать до 10 одновременных «тестов» и повторять их каждые 10 секунд. Вероятно, это стоит какой-то «блокирующий» процесс (с использованием flock), чтобы упростить использование проверки cron, если ваш скрипт «демон» все еще запущен.

Это было бы что-то вроде:

open (my $self, "<", $0) or die $!; 
flock ($self, 2 | 4) or die "$0 already running"; 

Вы можете сгореть его в хрон каждый так часто, и он будет перезапустить себя, если он умер по какой-то причине.

Но в любом случае - вы можете иметь несколько подпрограмм (например, ваши тестовые скрипты), которые все порождаются автономно (а для бонусных очков - они будут работать параллельно).

+0

Спасибо. Я сделаю это. Это может сделать именно то, что мне нужно. Как упоминалось выше @Borodin, это не полностью объясняет описанную мной «запись», но, как я думаю, вы не согласны с комментарием, я могу запустить другую подпрограмму, которая проверяет правильность добавления выходных файлов. Я больше буду работать над этой проблемой и дам вам знать, разрешит ли она мою проблему. Еще раз спасибо. – secJ

+0

У меня возникли проблемы с вызовом разыменования 'sub fetch_cpu_stats', происходящим в строке 30' & {$ test_list {$ test}} ($ target); '. Я получаю следующую ошибку: «Невозможно использовать неопределенное значение в качестве ссылки подпрограммы». Я не уверен, где проблема. Синтаксис выглядит корректно для меня, и '$ test', похоже, получает соответствующий coderef. Однако, если я сам вызываю '& fetch_cpu_stats' вместо того, чтобы переходить к разыменованию хэша'% test_list', он, похоже, работает нормально. Любые мысли об этом? Опять же, я очень ржавый и, возможно, здесь что-то не хватает. – secJ

+0

Это должно работать, но в качестве альтернативы - '$ test_list {$ test} -> ($ target);' должен делать то же самое. – Sobrique