ネットワーク監視のために、ping死活監視プログラムの作成を依頼されたので記録します。
かなり簡素なものです。
あと、このとき初めてPerlでロクなプログラム書きました。
#スレッド生成#
100対象以上に4秒程の間隔でpingを実行する必要があったため、スレッド処理を行っています。
今思えば、初言語で並列処理とかよくやったなって感じですね...
autoPing.pl
use threads;
foreach my $i(0 .. $#targetList){
my $thread = threads->new(
¥&runPing,
$targetList[$i]->[0],
$targetList[$i]->[1],
$targetList[$i]->[2],
$targetList[$i]->[3]
);
push(@threads, $thread);
}
foreach(@threads){
$_->join;
}
Perlの並列処理って凄くわかりやすいです。
#まとめ#
こんな感じになりました。
autoPing.pl
use strict;
use warnings;
use threads;
use Time::HiRes;
my $file = shift;
unless ($file) {
die "Usage: ¥$ perl $0 <file>.¥n";
}
my @threads;
my $target = ['ip','name','interval','size'];
my @targetList = &getTargetList($file,$target);
print "Create threads.¥n";
foreach my $i(0 .. $#targetList){
my $thread = threads->new(
¥&runPing,
$targetList[$i]->[0],
$targetList[$i]->[1],
$targetList[$i]->[2],
$targetList[$i]->[3]
);
push(@threads, $thread);
}
print "Join threads.¥n";
foreach(@threads){
$_->join;
}
sub runPing {
my ($ip,$name,$interval,$size) = @_;
my $time = sprintf "%0.3f",0;
while(1){
my $startTime = Time::HiRes::time;
my $result = `ping $ip -c 1 -s $size`;
my $timeStamp = &getTimestamp;
if($result =~ /¥s1¥sreceived/s){
$result = "OK : $timeStamp : $name ($ip) -> Packet trancemitted and received. (interval: ${time}s)¥n";
} elsif ($result =~ /Destination/s) {
$result = "NG : $timeStamp : $name ($ip) -> Destination Net unreachable. (interval: ${time}s)¥n";
} elsif ($result =~ /¥s0¥sreceived/s) {
$result = "OK?: $timeStamp : $name ($ip) -> Packet trancemitted but no received. (interval: ${time}s)¥n";
} else {
$result = "NG : $timeStamp : $name ($ip) -> $result (interval: ${time}s)¥n";
}
no strict "refs";
my $fh = "LOG$ip";
open(${$fh},">> ./log/$ip¥_$name.log") or die("Error : $!");
print {${$fh}} $result;
close(${$fh});
while($interval > Time::HiRes::time - $startTime){
threads->yield();
}
$time = sprintf "%0.3f",Time::HiRes::time - $startTime;
}
}
sub getTargetList {
# my (@target) = @_;
my $targetList = [];
open(TARGET,"<",$_[0]) or die("Error : $!");
while(<TARGET>){
chomp;
my @target = split(',',);
push @$targetList, ¥@target;
}
close(TARGET);
for my $target (@$targetList) {
print join(',',@$target)."¥n";
}
wantarray ? return @$targetList : $targetList;
}
sub getTimestamp {
my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(time);
return sprintf("%04d%02d%02d_%02d%02d%02d",$year+1900,$mon+1,$mday,$hour,$min,$sec);
}
実行する際に対象名やIPアドレスをCSVにしたファイルを読み込ませます。
出力結果は対象毎にファイルに分けられて保存されます。
↓出力結果はこんな感じです。
OK : 20140606_184733 : 対象名 (192.168.*.*) -> Packet trancemitted and received. (interval: 0.000s)
OK : 20140606_184738 : 対象名 (192.168.*.*) -> Packet trancemitted and received. (interval: 4.000s)
OK : 20140606_184742 : 対象名 (192.168.*.*) -> Packet trancemitted and received. (interval: 4.000s)
OK : 20140606_184746 : 対象名 (192.168.*.*) -> Packet trancemitted and received. (interval: 4.011s)
OK : 20140606_184750 : 対象名 (192.168.*.*) -> Packet trancemitted and received. (interval: 4.014s)
すこし遅延してますね。むむむ
まぁこの時100対象位にping撃ってたんで無理ないか...
hinemosとか、ああいうネットワーク監視ソフトってどんな仕組みなんでしょうね。
気になります。