设为首页 收藏本站
查看: 1595|回复: 0

nagios监控 mysql 表结构

[复制链接]

尚未签到

发表于 2015-11-23 08:26:12 | 显示全部楼层 |阅读模式
引言

为了给客户演示对mysql表结构的监控,在搜了很久之后发现不得不自己写一个脚本了。percona这么牛B的公司竟然没有提供一个这方面的工具,看来客户的要求有点花儿不实啊。。。这个问题一共花费了我两天时间去解决(个人shell脚本一般,能力也一般),所以总结一下。
实现设想

过程中一共有三种想法:
1. 由于mysql的informarion_schema.columns这个表存储这所有表的表结构,因此第一个设想是想对information_schema.columns这个表不停的扫描,保留老数据,将本次扫描的数据与老数据进行比较,如果发现有所不同则肯定发生了 alter table的操作,即表结构发生了变化
2. mysql的表都存在/data目录下,表结构都有一个单独的文件***.frm文件进行存储(innodb表需要设置innodb_file_per_table),所以第二个想法是监控/data目录的frm文件带大小,如果大小发生变化则认为是发生了表结构的变化,这种方法实现起来比第一种简单,但是准确性肯定不是很好,很有可能表结构更改了为frm文件的大小没变。


方法一实现:

一共需要三个临时文件,一个用于存储当前表结构信息,一个用于存储上一次检查的表结构信息,一个用于存储表结构变化的表名。
脚本名为check_mysql_table,代码如下
#!/bin/sh
# ########################################################################
# This program is used to check whether mysqld run on this machine
# ########################################################################
# ########################################################################
# Redirect STDERR to STDOUT; Nagios doesn't handle STDERR.
# ########################################################################
exec 2>&1
# ########################################################################
# Set up constants, etc.
# ########################################################################
STATE_OK=0
STATE_WARNING=1
STATE_CRITICAL=2
STATE_UNKNOWN=3
STATE_DEPENDENT=4
TMPFILENEW="/tmp/table_frm.new"
TMPFILEOLD="/tmp/table_frm.old"
TMPFILERESULT="/tmp/alter_table"
# ########################################################################
# Run the program.
# ########################################################################
main() {
# Get options
for a; do
case "${a}" in
-c)              shift; OPT_CRIT="${1}"; shift; ;;
--defaults-file) shift; OPT_DEFT="${1}"; shift; ;;
-g)              shift; OPT_UNIX_GROUP="${1}"; shift; ;;
-H)              shift; OPT_HOST="${1}"; shift; ;;
-l)              shift; OPT_USER="${1}"; shift; ;;
-L)              shift; OPT_LOPA="${1}"; shift; ;;
-p)              shift; OPT_PASS="${1}"; shift; ;;
-P)              shift; OPT_PORT="${1}"; shift; ;;
-S)              shift; OPT_SOCK="${1}"; shift; ;;
-u)              shift; OPT_UNIX_USER="${1}"; shift; ;;
-w)              shift; OPT_WARN="${1}"; shift; ;;
-e)              shift; OPT_EMAIL="${1}"; shift; ;;
-d)              shift; OPT_DATABASE="${1}"; shift; ;;
--version)       grep -A2 '^=head1 VERSION' "$0" | tail -n1; exit 0 ;;
--help)          perl -00 -ne 'm/^  Usage:/ && print' "$0"; exit 0 ;;
-*)              echo "Unknown option ${o}.  Try --help."; exit 1; ;;
esac
done
OPT_UNIX_GROUP="${OPT_UNIX_GROUP:-mysql}"
OPT_UNIX_USER="${OPT_UNIX_USER:-mysql}"
if [ -e '/etc/smartmonitor/mysql.cnf' ]; then
OPT_DEFT="${OPT_DEFT:-/etc/smartmonitor/mysql.cnf}"
fi
if is_not_sourced; then
if [ -n "$1" ]; then
echo "WARN spurious command-line options: $@"
exit 1
fi
fi
if [ "${OPT_DEFT}${OPT_HOST}${OPT_USER}${OPT_PASS}${OPT_PORT}${OPT_SOCK}" ]; then
if [ ! "${OPT_DATABASE}" ]
then
OPT_DATABASE=" not in ('mysql','information_schema','performance_schema','test')"
TABLE_DATA=`mysql_exec  "SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema not in ('mysql','information_schema','test','performance_schema')"`
else
OPT_DATABASE="='"${OPT_DATABASE}"'"
TABLE_DATA=`mysql_exec "SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema"${OPT_DATABASE} `
fi
fi
if [ ! "${TABLE_DATA}" ]
then
echo "WARNING no tables in the databases"
exit 1
fi
echo $TABLE_DATA|awk '{gsub("def","\ndef");print}'>$TMPFILENEW
sed -i '1d' $TMPFILENEW
if [ -f "$TMPFILEOLD" ]
then
cat $TMPFILEOLD|while read Line
do
grep -q """${Line}""" $TMPFILENEW
if [ $? -ne 0 ]
then
Alter_table=`echo $Line|awk {'print $2"."$3"."$4'}`
echo $TABLE_NAMES |grep -q "$Alter_table"
if [ $? -ne 0 ]
then
TABLE_NAMES=${TABLE_NAMES}" "${Alter_table}
echo $TABLE_NAMES>$TMPFILERESULT
fi
fi
done
fi
cp $TMPFILENEW $TMPFILEOLD
if [ ! -f $TMPFILERESULT  ]
then
NOTE="OK,no table alter"
else
TABLE_NAMES=`cat $TMPFILERESULT`
NOTE="WARNING, alter table:"${TABLE_NAMES}
if [ "${OPT_EMAIL}" ]
then
echo $NOTE | /bin/mail -s "SERVICE NOTIFITATION:ALTER TABLE" $OPT_EMAIL
fi
fi
rm -f $TMPFILERESULT
echo $NOTE
}
# ########################################################################
# Execute a SmartSQL command.
# ########################################################################
mysql_exec() {
mysql ${OPT_DEFT:+--defaults-file="${OPT_DEFT}"} ${OPT_HOST:+-h"${OPT_HOST}"} ${OPT_USER:+-u"${OPT_USER}"} \
${OPT_PASS:+-p"${OPT_PASS}"} ${OPT_SOCK:+-S"${OPT_SOCK}"} ${OPT_PORT:+-P"${OPT_PORT}"} \
${OPT_LOPA:+--login-path="${OPT_LOPA}"} -ss -e "$1"
}

# ########################################################################
# Determine whether this program is being executed directly, or sourced/included
# from another file.
# ########################################################################
is_not_sourced() {
[ "${0##*/}" = "check_mysql_table" ] || [ "${0##*/}" = "bash" -a "$_" = "$0" ]
}
# ########################################################################
# Execute the program if it was not included from another file.
# This makes it possible to include without executing, and thus test.
# ########################################################################
if is_not_sourced; then
OUTPUT=$(main "$@")
EXITSTATUS=$STATE_UNKNOWN
case "${OUTPUT}" in
UNK*)  EXITSTATUS=$STATE_UNKNOWN;  ;;
OK*)   EXITSTATUS=$STATE_OK;       ;;
WARN*) EXITSTATUS=$STATE_WARNING;  ;;
CRIT*) EXITSTATUS=$STATE_CRITICAL; ;;
esac
echo "${OUTPUT}"
exit $EXITSTATUS
fi
# ############################################################################
# Documentation
# ############################################################################
: <<'DOCUMENTATION'
=pod
=head1 NAME
check-mysql-table - Alert when MySQL table alter happen.
=head1 SYNOPSIS
Usage: check-mysql-table [OPTIONS]
Options:
-c CRIT         ignore now
--defaults-file FILE Only read mysql options from the given file.
Defaults to /etc/nagios/mysql.cnf if it exists.
-g GROUP        MySQL groupusername
-H HOST         MySQL hostname.
-l USER         MySQL username.
-L LOGIN-PATH   Use login-path to access MySQL (with MySQL client 5.6).
-p PASS         MySQL password.
-P PORT         MySQL port.
-S SOCKET       MySQL socket file.
-w WARN         When table alter happen return Warning.default value
-e EMAIL        Once Alter send a email to this address
-d DATABASE     The tables of this databases will be monitored.
Defaults to all databases except mysql information_scheme test and performance_schema
--help          Print help and exit.
--version       Print version and exit.
Options must be given as --option value, not --option=value or -Ovalue.
Use perldoc to read embedded documentation with more details.

=back
Examples:
# /usr/local/nagios/libexec/check-mysql-table -H 127.0.0.1 -P 3306 -l root -d weibo
OK no alter table
=head1 PRIVILEGES
This plugin executes the following commands against MySQL:
=over
=item *
C<SELECT * FROM  INFORMATION_SCHMEMA.COLUMNS;>

=back
This plugin executes no UNIX commands that may need special privileges.
=head1 VERSION
GreatOpenSource Monitoring Plugins check_mysql_table 1.0
=cut
check_mysql_table - Return WARNING if table alter happen

DOCUMENTATION

程序的框架参考了percona的mysql监控脚本&#26684;式。
虽然代码较多,但是思想很简单。
遇到的问题

1 临时文件路径问题,一开始程序中的临时文件用的是相对路径,但是nagios运行时,会将所有的临时文件都在temp_path=/tmp ,这个配置选项指出了临时文件的位置。
2.管道问题,在处理文件时候,也就是下面这段代码
  cat $TMPFILEOLD|while read Line
do
grep -q &quot;&quot;&quot;${Line}&quot;&quot;&quot; $TMPFILENEW
if [ $? -ne 0 ]
then
Alter_table=`echo $Line|awk {'print $2&quot;.&quot;$3&quot;.&quot;$4'}`
echo $TABLE_NAMES |grep -q &quot;$Alter_table&quot;
if [ $? -ne 0 ]
then
TABLE_NAMES=${TABLE_NAMES}&quot; &quot;${Alter_table}
echo $TABLE_NAMES>$TMPFILERESULT
fi
fi
done

这里的变量TABLE_NAME保存着表结构发生变化的表名字,但是由于是在一个管道中进行的,这个变量的&#20540;传不出来,出了这个while循环后就不能用了,所以把这个变量的&#20540;写入了一个临时文件中。


方法二的实现

思想简单,代码如下
#!/bin/sh
# ########################################################################
# This program is used to check whether mysqld run on this machine
# ########################################################################
# ########################################################################
# Redirect STDERR to STDOUT; Nagios doesn't handle STDERR.
# ########################################################################
exec 2>&1
# ########################################################################
# Set up constants, etc.
# ########################################################################
STATE_OK=0
STATE_WARNING=1
STATE_CRITICAL=2
STATE_UNKNOWN=3
STATE_DEPENDENT=4
TMPFILE=&quot;/tmp/table_frm_size&quot;
# ########################################################################
# Run the program.
# ########################################################################
main() {
# Get options
for o; do
case &quot;${o}&quot; in
-c)              shift; OPT_CRIT=&quot;${1}&quot;; shift; ;;
--defaults-file) shift; OPT_DEFT=&quot;${1}&quot;; shift; ;;
-g)              shift; OPT_UNIX_GROUP=&quot;${1}&quot;; shift; ;;
-H)              shift; OPT_HOST=&quot;${1}&quot;; shift; ;;
-l)              shift; OPT_USER=&quot;${1}&quot;; shift; ;;
-L)              shift; OPT_LOPA=&quot;${1}&quot;; shift; ;;
-p)              shift; OPT_PASS=&quot;${1}&quot;; shift; ;;
-P)              shift; OPT_PORT=&quot;${1}&quot;; shift; ;;
-S)              shift; OPT_SOCK=&quot;${1}&quot;; shift; ;;
-u)              shift; OPT_UNIX_USER=&quot;${1}&quot;; shift; ;;
-w)              shift; OPT_WARN=&quot;${1}&quot;; shift; ;;
-e)              shift; OPT_EMAIL=&quot;${1}&quot;; shift; ;;
-d)              shift; OPT_DATABASE=&quot;${1}&quot;; shift; ;;
--version)       grep -A2 '^=head1 VERSION' &quot;$0&quot; | tail -n1; exit 0 ;;
--help)          perl -00 -ne 'm/^  Usage:/ && print' &quot;$0&quot;; exit 0 ;;
-*)              echo &quot;Unknown option ${o}.  Try --help.&quot;; exit 1; ;;
esac
done
OPT_UNIX_GROUP=&quot;${OPT_UNIX_GROUP:-smartsql}&quot;
OPT_UNIX_USER=&quot;${OPT_UNIX_USER:-smartsql}&quot;
OPT_EMAIL=&quot;${OPT_EMAIL:-}&quot;
if [ -e '/etc/smartmonitor/smartsql.cnf' ]; then
OPT_DEFT=&quot;${OPT_DEFT:-/etc/smartmonitor/smartsql.cnf}&quot;
fi
if is_not_sourced; then
if [ -n &quot;$1&quot; ]; then
echo &quot;WARN spurious command-line options: $@&quot;
exit 1
fi
fi
#NOTE=&quot;UNK could not determine the datadir location.&quot;
if [ ! &quot;${OPT_DATABASE}&quot; ]
then
echo &quot;CRITICAL,no database use&quot;
exit 2
fi
DATADIR=
NOTE=&quot;UNKOWN can not get the data dir &quot;
TABLENAMES=&quot;&quot;
if [ &quot;${OPT_DEFT}${OPT_HOST}${OPT_USER}${OPT_PASS}${OPT_PORT}${OPT_SOCK}&quot; ]; then
DATADIR=`smartsql_exec &quot;SELECT IF(@@datadir LIKE '/%', @@datadir, CONCAT(@@basedir, @@datadir))&quot; `
fi
if [ ! $? ]
then
echo &quot;UNKOWN error&quot;
exit 3  
fi
FindDir=${DATADIR}${OPT_DATABASE}&quot;/&quot;
if [ ! -f &quot;$TMPFILE&quot; ]
then
touch $TMPFILE
for File in `find $FindDir -name &quot;*.frm&quot;`
do
tmp=${File##*/}
filename=${tmp%.*}
set `ls -il $File`
echo ${filename}&quot;:&quot;$6>>$TMPFILE
done
else
for File in `find $FindDir -name &quot;*.frm&quot;`
do
tmp=${File##*/}
filename=${tmp%.*}
set `ls -il $File`
size=$6
searchstr=${filename}
result=`grep  &quot;$searchstr&quot; $TMPFILE`
if [ $? -eq 0 ]
then
oldsize=${result##*:}
if [ $size -ne $oldsize ]
then
TABLE_NAMES=${TABLE_NAMES}&quot; &quot;${filename}
fi
fi
done
fi
if [ x&quot;$TABLE_NAMES&quot; = x ]
then
NOTE=&quot;OK,no table alter&quot;
else
NOTE=&quot;WARNING, alter table:&quot;${TABLE_NAMES}
if [ &quot;${OPT_EMAIL}&quot; ]
then
echo $NOTE | /bin/mail -s &quot;SERVICE NOTIFITATION:ALTER TABLE&quot; $OPT_EMAIL
fi
rm -rf $TMPFILE
touch $TMPFILE
for File in `find $FindDir -name &quot;*.frm&quot;`
do
tmp=${File##*/}
filename=${tmp%.*}
set `ls -il $File`
echo ${filename}&quot;:&quot;$6>>$TMPFILE
done
fi
echo $NOTE
}
# ########################################################################
# update $TMPFILE.
# ########################################################################
# ########################################################################
# Execute a SmartSQL command.
# ########################################################################
smartsql_exec() {
smartsql ${OPT_DEFT:+--defaults-file=&quot;${OPT_DEFT}&quot;} ${OPT_HOST:+-h&quot;${OPT_HOST}&quot;} ${OPT_USER:+-u&quot;${OPT_USER}&quot;} \
${OPT_PASS:+-p&quot;${OPT_PASS}&quot;} ${OPT_SOCK:+-S&quot;${OPT_SOCK}&quot;} ${OPT_PORT:+-P&quot;${OPT_PORT}&quot;} \
${OPT_LOPA:+--login-path=&quot;${OPT_LOPA}&quot;} -ss -e &quot;$1&quot;
}
# ########################################################################
# A wrapper around pidof, which might not exist. The first argument is the
# command name to match.
# ########################################################################
_pidof() {
if ! pidof &quot;${1}&quot; 2>/dev/null; then
ps axo pid,ucomm | awk -v comm=&quot;${1}&quot; '$2 == comm { print $1 }'
fi
}

# ########################################################################
# Determine whether this program is being executed directly, or sourced/included
# from another file.
# ########################################################################
is_not_sourced() {
[ &quot;${0##*/}&quot; = &quot;check_smartsql_table&quot; ] || [ &quot;${0##*/}&quot; = &quot;bash&quot; -a &quot;$_&quot; = &quot;$0&quot; ]
}
# ########################################################################
# Execute the program if it was not included from another file.
# This makes it possible to include without executing, and thus test.
# ########################################################################
if is_not_sourced; then
OUTPUT=$(main &quot;$@&quot;)
EXITSTATUS=$STATE_UNKNOWN
case &quot;${OUTPUT}&quot; in
UNK*)  EXITSTATUS=$STATE_UNKNOWN;  ;;
OK*)   EXITSTATUS=$STATE_OK;       ;;
WARN*) EXITSTATUS=$STATE_WARNING;  ;;
CRIT*) EXITSTATUS=$STATE_CRITICAL; ;;
esac
echo &quot;${OUTPUT}&quot;
exit $EXITSTATUS
fi
# ############################################################################
# Documentation
# ############################################################################
: <<'DOCUMENTATION'
check_smartsql_table - Return WARNING if table alter happen
Usage: check_smartsql_table
DOCUMENTATION



参考

1. http://www.percona.com/blog/2014/02/26/monitor-alter-table-progress-innodb_file_per_table/

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-142352-1-1.html 上篇帖子: nagios安装配置笔记 下篇帖子: Redhat 5.2 配置nagios
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表