在监控宝注册了站点监控服务,天天给我发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