在监控宝注册了站点监控服务,天天给我发email报告站点下线。无奈只好发了个tk询问原因,客服回复说网络一直木有问题。只要写个小的监控程序丢服务器跑着,看看是否是真的是服务器掉线。
找了一下perl的ping模块,最终选了Net::Ping,因为可以记录响应时间。使用Sqlite数据库保存数据,用highcharts绘制时间的折线图。
以下为相关代码:
alive.pl收集特定几个站点的ping响应时间,使用cron定时执行。
#!/usr/bin/perl
use strict;
use warnings;
use DBI;
use Net::Ping;
my $dbh = DBI->connect("dbi:SQLite:dbname=alive.db","","");
my $dbconn = $dbh->prepare("SELECT * FROM host");
$dbconn->execute();
my @domains;
while (my @row_ary = $dbconn->fetchrow_array) {
my ($id, $domain) = @row_ary;
push(@domains, $domain);
}
my $p = Net::Ping->new("icmp", 5);;
$p->hires();
foreach my $domain (@domains) {
my ($ret, $rtt, $ip) = $p->ping($domain);
my $timestamp = time();
my $time = $rtt * 1000;
$time = $time > 5000 ? -10 : $time;
$dbh->do( "insert into alive values( $timestamp, '$domain', '$ip', $time )");
if ($dbh->err()) {
die "$DBI::errstr\n";
}
sleep(1);
}
$p->close();
$dbh->disconnect();
view.pl根据alive.pl收集到的数据进行绘图,得到时间曲线。
#!/usr/bin/perl
use strict;
use warnings;
use POSIX qw(tzset);
use Math::Round;
use Date::Calc qw(Mktime);
use CGI;
use DBI;
use JSON;
my $q = new CGI;
$ENV{TZ} = 'Asia/Shanghai';
tzset;
print $q->header("text/html; charset=UTF-8");
my $dbh = DBI->connect("dbi:SQLite:dbname=alive.db","","");
my $dbconn = $dbh->prepare("SELECT * FROM host");
my $ts = $q->param("timestamp");
my ($year,$mon,$day,$hour,$min);
if($ts) {
($year,$mon,$day,$hour,$min) = ($ts=~/(\d+)-(\d+)-(\d+) (\d+):(\d+)/);
$ts = Mktime($year, $mon, $day, $hour, $min, 0);
}
else {
$ts = time();
}
$dbconn->execute();
my @domains;
while (my @row_ary = $dbconn->fetchrow_array) {
my ($id, $domain) = @row_ary;
push(@domains, $domain);
}
my $series;
my $timestamp;
my $date;
foreach my $domain (@domains) {
my $dbconn = $dbh->prepare("SELECT * FROM alive WHERE host='$domain' and timestamp < $ts ORDER BY timestamp DESC LIMIT 12");
$dbconn->execute();
my $data;
my $x;
$data->{'name'} = $domain;
while (my @row_ary = $dbconn->fetchrow_array) {
my ($timestamp, $host, $ip, $time) = @row_ary;
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($timestamp);
$mon++; $year += 1900;
$date = "$year年$mon月$mday日" unless $date;
push(@{$data->{'data'}}, nearest(.01,$time));
push(@{$x}, "$hour:$min");
}
@{$data->{'data'}} = reverse @{$data->{'data'}};
@{$x} = reverse @{$x};
push(@{$series}, $data);
$timestamp = $x;
}
$series = encode_json($series);
$timestamp = encode_json($timestamp);
print <<"EOF";
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>网络监控</title>
<script src="meteora/meteora.js"></script>
<script type="text/javascript" src="jquery.min.js"></script>
<script src="highcharts.js"></script>
<script src="exporting.js"></script>
<script type="text/javascript">
\$(function () {
var chart;
\$(document).ready(function() {
chart = new Highcharts.Chart({
chart: {
renderTo: 'container',
type: 'line',
marginRight: 130,
marginBottom: 25
},
title: {
text: '$date',
x: -20 //center
},
xAxis: {
categories: $timestamp
},
yAxis: {
title: {
text: 'Time (ms)'
},
plotLines: [{
value: 0,
width: 1,
color: '#808080'
}]
},
tooltip: {
formatter: function() {
return '<b>'+ this.series.name +'</b><br/>'+
this.x +': '+ this.y +'ms';
}
},
legend: {
layout: 'vertical',
align: 'right',
verticalAlign: 'top',
x: -10,
y: 100,
borderWidth: 0
},
series: $series
});
});
});
Meteora.uses('Meteora.Calendar');
Meteora.onStart(
function () {
new Calendar(
'timestamp',
{
format: '%Y-%m-%d %H:%i',
minYear: 2000,
showHour: true,
showMinute: true,
showMeridiem: true
});
}
);
</script>
</head>
<body>
<div id="container" style="min-width: 400px; height: 400px; margin: 0 auto"></div>
<form action="view.pl" method="post">
<input id="timestamp" name="timestamp" type="text" />
<input type="submit" value="查看" />
</from>
</body>
</html>
EOF