单机监控-shell脚本监测java应用程序是否宕机
前言
由于工作中很多项目需要java应用程序在后台执行任务,但是有些时候后台运行的java应用程序会莫名其妙的死掉,此时运维/运营人员无法及时发现宕机的应用程序,只能够通过业务流程不正常才能够发现宕机的应用,对业务有很大的影响,由于公司服务器资源比较有限,无法部署统一的监测系统,特采用shell脚本的方式来监测java的应用进程是否正常运行,无须在业务代码中嵌入监控代码,做到低耦合,高内聚。
监测原理
- 原理图
- java应用启动时,采用自定义脚本方式启动,然后将应用的当前进程号进行应用的根目录下生成pid.txt文件
- shell脚本执行的时候查找指定目录下的所有pid.txt文件,然后根据每个pid.txt中的进程号判断当前的进程是否存活
- 如果根据进程号没有找到指定的进程则认为进程死掉,主动发送告警(此处采用钉钉群机器人的方式告警)
监控脚本
-
java应用启动脚本
#!/bin/sh root_dir=$(dirname $(readlink -f "$0")) class_path=$root_dir/bin:$root_dir/lib/* pid_file=$root_dir/pid.txt console_file=$root_dir/logs/console.out error_file=$root_dir/logs/errors.out echo "Starting channel app in $root_dir ..." if [ ! -f $pid_file ]; then nohup java -cp $class_path com.xxx.StartUp >> $console_file 2>&1 & echo $! > $pid_file echo "[$(date)]: app in $root_dir started successful!" >> $console_file echo "pid = $!" >> $console_file echo "[$(date)]: app in $root_dir started successful!" echo "pid = $!" else echo "****** Starting FAILED!! channel app in $root_dir is already running !!!" fi
-
java应用停止脚本
#!/bin/sh root_dir=$(dirname $(readlink -f "$0")) pid_file=$root_dir/pid.txt echo $root_dir if [ -f $pid_file ]; then PID=$(cat $pid_file); echo "Stopping app in $root_dir ..." kill $PID; echo "app [pid=$PID] in $root_dir has been stopped" rm $pid_file else echo "Stopping FAILED! app in $root_dir is not running !!!" fi
-
shell监控脚本
#!/bin/sh ######################################## #功能:自动检测java应用程序宕机,并主动钉钉告警 #版本:1.1 #作者:silly at 20190708 #版本说明: # v1.0 # 1)实现通过进程来判断应用程序是否宕机 # 2)检测到宕机后通过钉钉机器人发送消息到钉钉群里告警 # # v1.1 # 1)删除7天前的日志文件 # 2)修复通过进程号判断是否宕机出现包含的bug # 例如:进程号330,此时有运行的34330,则grep 330 会出现两条记录,此时检测会认为宕机 # grep $pid ===>grep -w $pid # 3)修复定时任务无法获取当前脚本所在目录,logPath="`pwd`/logs" ===》logPath="/server/scripts/logs" # 4)修复定时任务中ifconfig命令无法使用,ifconfig ===》/sbin/ifconfig ######################################### #参数定义 #监控目录 monitorPath="/" #监控进程号文件名 monitorProcess="pid.txt" #钉钉access_token ddAccessToken="xxx" ddUrl="https://oapi.dingtalk.com/robot/send?access_token=$ddAccessToken" #日志目录 logPath="/server/scripts/logs" #日志文件 logFile="${logPath}/auto_monitor_down_application_`date +%F`.log" #判断日志目录是否存在 [ -d $logPath ] || mkdir -p $logPath #判断日志文件是否存在 [ -f $logFile ] || touch $logFile #打印日志 function logInfo(){ echo " `date '+%Y-%m-%d %H:%M:%S'` $1" >> $logFile } #发送钉钉消息 function sendDingding(){ #获取当前的ip localIp=`/sbin/ifconfig |grep inet |grep -v 127.0.0.1|grep -v inet6|awk '{print $2}'|tr -d "addr:"|tr "\n" "\t"` applicationPath=`dirname $1` #拼接钉钉消息 msgTopic="[单机检测宕机-发现宕机应用 ]" msgIp="IP:$localIp" msgApplication="应用位置:$applicationPath" msgTime="报警时间: `date '+%Y-%m-%d %H:%M:%S'`" msgRemark="请运营人员立即联系技术排查问题" msgContent=$msgTopic\\n\\n$msgIp\\n$msgApplication\\n$msgTime\\n\\n$msgRemark ddMsgTemplate='{"msgtype": "text","text": {"content": "<DING_TALK_MSG_CONTENT>"}, "at": {"atMobiles": [], "isAtAll": true}}' msg=${ddMsgTemplate/<DING_TALK_MSG_CONTENT>/$msgContent} response=`curl $ddUrl -H 'Content-Type: application/json' -d "$msg"` logInfo $response } logInfo "monitor start" find $monitorPath -type f -name $monitorProcess |while read file do pid=`cat $file` processCount=`ps -ef |grep -w $pid|grep -v 'grep'|wc -l` if [ $processCount -eq 1 ] then logInfo " `dirname $file` runing" else logInfo " `dirname $file` shutdown" sendDingding $file fi done #删除7天前的日志文件 find ${logPath}/ -type f -mtime +7 -name "*.log" |xargs rm -f logInfo "monitor end"
发送钉钉消息可参考博文:https://blog.csdn.net/cen50958/article/details/92230109
-
加入定时任务每10分钟执行一次
#每隔10分钟检查java应用程序是否宕机 */10 * * * * /bin/sh /server/scripts/auto_monitor_down_application.sh >/dev/null 2>&1