一、背景
自己寫了個監控MGR狀態的腳本,直接在Linux的Shell環境下可以執行成功,但是只要放到crontab里執行,就失敗,腳本內容如下
#!/bin/bash
MAIL_ADDR=`cat /data/mysql_monitor/m.conf |grep mailaddress |cut -d ":" -f2`
USER=`cat /data/mysql_monitor/m.conf |grep mysql_user |cut -d ":" -f2`
PASSWORD=`cat /data/mysql_monitor/m.conf |grep mysql_pwd |cut -d ":" -f2`
MYSQL_STAT_LOG=`cat /data/mysql_monitor/m.conf |grep mysql_stat |cut -d ":" -f2`
IP=`cat /data/mysql_monitor/m.conf |grep ip |cut -d ":" -f2`
MYSQL_PORT=`netstat -na|grep "LISTEN"|grep -w "3306"|awk -F[:" "]+ '{print $4}'`
DATE=$(date "+%Y-%m-%d %H:%M.%S")
#Check_status(){
STATUS=$(mysql -u$USER -p$PASSWORD --connect_timeout=5 -e "SELECT * FROM performance_schema.replication_group_members;" 2>&1 |sed -n '/group_replication_applier/p' |grep -w "ONLINE")
MGR=`echo $STATUS |grep ONLINE |awk '{print $5}' |head -n 1`
if [ "$MGR" = "ONLINE" ]
then
echo "MySQL MGR is ONLINE" > $MYSQL_STAT_LOG
else
echo "$DATE Server: $IP MySQL MGR status is not ONLINE,Please check MGR status!" > $MYSQL_STAT_LOG
python /data/mysql_monitor/mail.py 'mysql' $MAIL_ADDR "$IP Mysql Warn" < $MYSQL_STAT_LOG
fi
二、排查思路
一般這種情況都是由於環境變量沒有獲取到導致(所以為什么很多腳本里都會有一行export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin),可能包括腳本定義的環境變量,和系統本身的環境變量
腳本里定義的環境變量沒有獲取到
在腳本里引用的每個變量下一行,都加上echo $變量名並追加到文件中,例如:
# echo $MYSQL_USER >> /tmp/test
將腳本放到crontab中,然后觀察/tmp/test,看看是哪一個變量沒有獲取到
2.1系統環境變量沒有獲取到
比如我這次要用mysql命令,那么先查出mysql命令在哪里
# which mysql
/usr/local/mysql/bin/mysql
查看crontab執行的環境變量
[root@oratest52 mysql_monitor]# cat /etc/crontab
SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
[root@oratest52 mysql_monitor]# echo $PATH
/usr/local/mysql/bin/:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
可以發現cron的環境變量少了/usr/local/bin,/usr/local/sbin,/root/bin,/usr/local/mysql/bin/
三、解決辦法
在腳本里加入一行
export PATH=/usr/local/mysql/bin/:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
在我這個案例里,也可以在腳本執行mysql時用絕對路徑
/usr/local/mysql/bin/mysql
可見在我們寫腳本的時候,命令路徑最好是用絕對路徑,如果腳本用到一些非系統自帶的命令,最好是在腳本里聲明$PATH