我有一个bash脚本(我正在转换为perl),它以无限循环(while true; do
)运行,以轮询我们网络上的设备并将其响应记录到文本文件中。对于(while
)循环的每次迭代,该设备的文本文件都附有其最新信息。
我想让这个脚本始终运行 - 如果它被挂起,崩溃,或者不再写入相应的文本文件 - 它应该重新启动。
按照this StackOverflow问题中发布的建议,我可以编写以下bash脚本:
until myserver; do
echo "Server 'myserver' crashed with exit code $?. Respawning.." >&2
sleep 1
done
其中myserver
是投票程序。这将解决脚本意外崩溃或挂起的问题,假设在这些情况下发出了非零退出代码。但是,如果脚本没有完全失败/退出,但是以一种只是阻止它写出文本文件的方式失败 - 我也想在这种情况下重新启动脚本。这就是类似监视器的脚本的用武之地。我可以使用Python的watchdog
编写一个脚本,使用Observer
库监视正在生成的文本文件like in this example。我会触发停滞的文本文件为python脚本发出一个非零退出,然后按如下方式扩充上面的bash脚本:
until [myserver -o pythonMon]; do
echo "Server 'myserver' crashed with exit code $?. Respawning.." >&2
sleep 1
done
其中pythonMon
是监视文本文件是否正确更新的python脚本。不幸的是,这种方法需要三个脚本(主轮询脚本和两个监视脚本);这有点像kludge。我正在寻求优化/简化这种方法。有什么建议?理想情况下,我有一个脚本(至少一个监视脚本)来保持轮询脚本运行而不是两个。有没有办法直接将文件监控添加到bash或perl代码中?
这是在64位CentOS 6.5上运行的
答案 0 :(得分:1)
我正在做一些非常相似的事情来监控一堆设备。取决于轮询频率 - 我是通过cron产生的,间隔为3米。
请记住10s样本可能非常密集,并且可能并不总是必要的 - 它确实取决于您的目标。
无论如何,这个工作的工具是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";
然后你可以经常在cron中启动它,如果由于某种原因它会死掉它会自动重启。
但无论如何 - 你可以有多个子程序(例如你的测试脚本)全部自动生成(并且对于奖励积分 - 它们将并行运行)。