前言:
随着维护服务器的增多,每天一台台检查备份已经不切实际,即使通过email的方式(备份脚本执行完后将备份信息发送到指定邮箱)检查也要耗费不少的时间,每天做这种重复性且繁杂的事情对我们这类懒人来说简直痛不欲生。经过一次惨痛的教训之后,决定做个备份检查(监控)程序。
原理:
原理挺简单,本地服务器通过备份检查脚本检查备份文件是否存在,并将检查结果提交到sae的mysql数据库里,最后通过一个web页面将数据统一显示出来。
实例:
假设有5台服务器(web1~web5),备份项目有:msyql数据库、mongodb数据库和/data/img的rsync+inotify实时同步,具体的备份信息如下:
备份项目 | 本地备份保存路径及文件名 | 异地备份保存路径及文件名 |
rsync+inotify | /data/img | /bk/$hostname/img/* |
mysql | /data/bk/msyql/mysql_日期.tgz | /bk/$hostname/mysql/mysql_日期.tgz |
mongodb | /data/bk/mongodb/mongodb_日期.tgz | /bk/$hostname/mongodb/mongodb_日期.tgz |
程序文件说明:
文件名 | 功能 |
getdata.php | 用于获取客户端POST过来的数据并将数据提交到mysql数据库 |
bk.sh | 服务器上的备份检查脚本 |
bk.php | web页面 |
首先到创建数据库:
CREATE TABLE `bk_monitor` ( `id` smailint NOT NULL auto_increment, `hostname` varchar(20) default NULL, `rsync` tinyint default NULL, `mysql`varchar(20) default NULL, `mongodb` varchar(20) default NULL, `date` timestamp, PRIMARY KEY (`id`) )
getdata.php
用于获取客户端POST过来的数据并将数据提交到mysql数据库。
shell脚本中,只要使用curl -d xxx=xxx http://www.cszhi.com/getdata.php, 就可以将数据提交到服务器端的mysql数据库里。
< ?php $posts=$_POST; // 清除一些空白符号 foreach ($posts as $key => $value) { $posts[$key] = trim(addslashes($value)); } //一些变量初始化 $db="bk_monitor"; $type=$posts['type']; //0插入 & 1更新 switch ($type) { case 0: $hostname=$posts['hostname']; $rsync=$posts['rsync']; $mysql=$posts['mysql']; $mongodb=$posts['mongodb']; $sql="insert into $db(hostname,rsync,mysql,mongodb) values('$hostname','$rsync','$mysql','$mongodb')"; break; case 1: $hostname=$posts['hostname']; $rsync=$posts['rsync']; $mysql=$posts['mysql']; $mongo=$posts['mongo']; $sql="update $db set rsync='$rsync',mysql='$mysql',mongodb='$mongodb' where hostname='$hostname'"; break; default: exit('error!!!'); } //操作数据库 $conn = mysql_connect("localhost","root","aaabbb123","bk_monitor") or die("can't connect mysql:".mysql_error()); mysql_query($sql,$conn) or die("query error:".mysql_error().":".$sql); mysql_close($conn); ?>
bk.sh
服务器上的备份检查脚本。脚本有验证异备服务器上的文件是否存在,所以需要先在服务器上设置能ssh无密码登陆到异备服务器。
#!/bin/bash #Program: #check the backup file and submit to the sae database #History: #2013/12/31 caishzh #变量初始化 HOSTNAME=$(hostname) TODAY=$(date +%Y%m%d) REMOTEIP="10.35.14.55" #这里是异备服务器的ip地址 TIMESTAMP=$(date +%s) TIMESTAMPFILE="/data/img/tmp/$TIMESTAMP" [ -f "/data/img/tmp" ] || mkdir /data/img/tmp LOG="/var/log/bk.log" URL="http://webshot.sinaapp.com/getdata.php" [ "$1" == 1 ] && TYPE=0 || TYPE=1 #函数:检查本地备份文件和异地备份文件是否存在 function isExistFile() { [ -f $1/$2 ] || { echo 2;echo "$1/$2 doesn't exist...">>$LOG;exit; } #判断远程文件是否存在 if [ $(ssh -o ConnectTimeout=10 $REMOTEIP "test -f $3/$2 && echo true || echo false") == "true" ];then size=$(ssh -o ConnectTimeout=10 $REMOTEIP "ls -lh $3/$2|cut -d' ' -f5") echo "0_$size" else { echo 1;echo "remote file ${REMOTEIP}:$3/$2 doesn't exist...">>$LOG;exit; } fi } echo "=====$(date +'%F %T') start=====" >>$LOG #mysql和mongodb备份文件检查 MYSQBKFILE="$(isExistFile /data/bk/mysql mysql_${TODAY}.tgz /bk/${HOSTNAME}/mysql)" MONGODBBKFILE="$(isExistFile /data/bk/mongodb mongodb_${TODAY}.tgz /bk/${HOSTNAME}/mysql)" #rsync实时同步检查 #在同步目录的tmp目录下,touch一个文件(文件名就是当前时间戳),sleep 5秒后,再判断远程目录是否存在这个文件,存在则rsync同步正常,不存在则异常 #sleep的时间可以根据自己服务器的情况调整 touch $TIMESTAMPFILE sleep 5 if [ $(ssh -o ConnectTimeout=10 $REMOTEIP "test -f /bk/${HOSTNAME}/img/tmp/${TIMESTAMP} && echo true || echo false") != "true" ];then RSYNCBAK=2 echo "rsync error..." >>$LOG fi RSYNCBAK=${RSYNCBAK:=0} #将数据提交至数据库 curl --connect-timeout 10 -d type=${TYPE} -d rsync="${RSYNCBAK}" -d mysql="${MYSQBKFILE}" -d mongodb="${MONGODBBKFILE}" -d hostname="${HOSTNAME}" $URL echo -e "=====$(date +'%F %T') finish=====n" >>$LOG
第一次执行时,脚本后面加个参数1,往数据库里新插入一条数据:
sh /root/tool/bk.sh 1
将bk.sh放到crontab,每天早上8点定时运行:
echo "0 8 * * * root sh /root/tool/bk.sh" >>/etc/crontab
bk.php web页面:
< !DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="content-type" content="text/html;charset=GB2312"/> <title>bk monitor</title> <link rel="stylesheet" href="style.css"> </link></head> <body> <h2>bk monitor</h2> <table border='1'> <tr> <th>id</th> <th>hostname</th> <th>rsync</th> <th>mysql</th> <th>mongodb</th> <th>date</th> </tr> < ?php function status($bkname) { $str=explode("_",$bkname); $status=(int)$str[0]; if ($status==0) { if(empty($str[1])) echo "<td>OK"; else echo "<td>OK $str[1]</td>"; } elseif ($status==1) { echo "<td>WARN</td>"; } elseif($bkname==2) { echo "<td>ERROR</td>"; } else { echo "<td>UNKNOW</td>"; } } //直接用sae提供的SaeMysql类操作mysql数据库 $mysql = new SaeMysql(); $sql = "SELECT * FROM bk_monitor"; $data = $mysql->getData( $sql ); //getDate返回的是二维数组,用foreach遍历下 foreach($data as $value) { echo "<tr>"; echo "<td>".$value['id']."</td>"; echo "<td>".$value['hostname']."</td>"; status($value['rsync']); status($value['mysql']); status($value['mongodb']); echo "<td>".$value['date']."</td>"; echo "</tr>"; } ?> </table> </body> </html>
如果想要显示的界面更加直观漂亮点,可以使用bootstrap做点样式,效果如下: