由于程序设计不合理或者瞬间高并发访问时,很有可能会触发OOM(Out of memory),这里指的是操作系统级别的OOM。具体什么是OOM,以及怎样发生这里不在赘述,因为笔者认为这是IT从业工作者的基本常识了。本篇主要记录一下生产环境时对发生OOM的程序进行监控,便于我们及时发现以及事后问题的复盘。

在做这个监控时,笔者也做了很多考察搜索,幻想着会有那么一两个成熟的开源软件能实现这个监控,事与愿违,笔者并未找到这样的工具,无奈之下,只好自己动手实现了一个略显粗糙的程序来达到我的目的。

实现思路:

    Apr 18 12:11:25 php001 kernel: Out of memory: Kill process 13546 (php-fpm) score 31 or sacrifice child

系统每次触发OOM时会在/var/log/message文件下记下当时系统的运行状况,以及被杀程序的pid和评分。因此笔者从此文件入手,写下了这样一个脚本。

1、目录结构如下:
oom_monitor位于共享存储NFS上,生产环境的机器都挂载了该NFS,因此所有机器上都会有这么一个目录 [admin@prod.001:/mnt/alinas]$ tree -L 1 oom_monitor/
oom_monitor/
├── bin #存放可执行的脚本文件
└── log #存放日志文件 [admin@prod.001:/mnt/alinas]$ tree -L 1 oom_monitor/bin/
oom_monitor/bin/
├── oom_check.sh #过滤"Out of memory"从/var/log/message,并生成对应文件保存在log目录下,用于后面的发送警报
├── oom_dingding.py #发送OOM对应信息到钉钉群
├── oom_mail.py #发送OOM对应信息到邮箱
└── oom_send.sh #用于触发发送报警信息到钉钉和邮箱

2、具体内容如下:

[admin@prod.001:/mnt/nfs/oom_monitor/bin]$ cat oom_check.sh
#!/bin/sh
#获取主机名
host_name=`hostname` #定义获取到的OOM日志存储位置
oom_scrape_file=/mnt/nfs/oom_monitor/log/oom_scrape_$host_name #定义上次发生OOM时的对应信息,用于去重,防止重复报警
old_oom_scrape_file=/mnt/nfs/oom_monitor/log/old_oom_scrape_$host_name #获取OOM报警信息
msg=$(sudo grep -i "out of memory" /var/log/messages|awk 'END {print}') #获取报警产生的时间
time=`echo $msg | awk '{print $3}'` #获取被杀的程序类型(java/php/mysql/...)
killed=`echo $msg | awk 'END {print $12}'` #获取上次OOM的信息
old_msg=`cat $old_oom_scrape_file` #判断两次信息是否相同,相同则不再记录此次信息,防止重复报警
if [ "$msg" == "$old_msg" ];then
exit 1
else #如果两次报警信息不相同则把这次获取的信息覆盖上次的信息
[ ! -z "$msg" ] && echo "$msg" > $old_oom_scrape_file
fi #记录此次信息持久化到文件
if [ ! -z "$msg" ];then
echo > $oom_scrape_file
echo -e "发生时间: $time" >> $oom_scrape_file
echo -e "日志信息: $msg" >> $oom_scrape_file
echo -e "被杀程序: $killed" >> $oom_scrape_file
echo -e "发生主机: $host_name" >> $oom_scrape_file
fi [admin@prod.001:/mnt/nfs/oom_monitor/bin]$ cat oom_send.sh
#!/bin/sh #定义获取到的OOM日志存储位置、OOM发送报警脚本位置
#这里用*的原因是:机器很多,每台机器一个文件,所以用*
oom_scrape_file=/mnt/nfs/oom_monitor/log/oom_scrape*
oom_warn_script=/mnt/nfs/oom_monitor/bin/oom_mail.py
oom_dingding_script=/mnt/nfs/oom_monitor/bin/oom_dingding.py
History_file=/mnt/nfs/oom_monitor/log/history_oom_scrape
basedir=/mnt/nfs/oom_monitor/log/
cd $basedir
for file in `ls $oom_scrape_file`
do
hostname=`grep "发生主机" $file|awk '{print $2}'`
warn_time=`grep "发生时间" $file |awk '{print $2}'`
killed=`grep "被杀程序" $file |awk '{print $2}'` #发送邮件报警,把日志信息全部发出去
/usr/local/bin/python3 $oom_warn_script $file #发送钉钉报警
/usr/local/bin/python3 $oom_dingding_script $hostname $killed $warn_time #报警信息发出后把日志信息追加到历史信息文件中,然后删除对应的oom信息文件,防止重复报警
cat $file >> $History_file && mv $file /tmp
done [admin@prod.001:/mnt/nfs/oom_monitor/bin]$ cat oom_mail.py
#!/usr/bin/env python3
'''
当收到系统OOM时,触发脚本发出邮件报警信息,信息格式如下: 您的主机「hostname」发生OOM,具体信息如下:
/var/log/message中的信息 '''
import os
import smtplib
from email.mime.text import MIMEText
from email.header import Header
import time
import sys
def send_email(file_name):
try: # 读取测试报告中的内容作为邮件的内容
with open(file_name, 'r', encoding='utf8') as f:
mail_body = f.read() # 发件人地址
send_addr = '此处替换为发件人的邮箱用户名' # 收件人地址
reciver_addr = ['接收人a的邮箱地址','接收人b的邮箱地址',] # 发送邮箱的服务器地址,这里用的是阿里云的
mail_server = 'smtp.mxhichina.com'
now = time.strftime("%Y-%m-%d %H:%M:%S") # 邮件标题
subject = '[OOM报警触发]' + now # 发件人的邮箱及邮箱密码
username = '此处替换为发件人的邮箱用户名'
password = '此处替换为发件人的邮箱密码' # 邮箱的内容和标题
message = MIMEText(mail_body, 'html', 'utf8')
message['From'] = send_addr
message['To'] = ','.join(reciver_addr)
message['Subject'] = Header(subject, charset='utf8') # 发送邮件,使用的使smtp协议
smtp = smtplib.SMTP() #端口注意下,通常服务器的25端口是关闭的,所以我这里用了80、或者465也阔以
smtp.connect(mail_server,80)
smtp.login(username, password)
smtp.sendmail(send_addr, message['To'].split(','), message.as_string())
smtp.quit()
print("邮件发送成功!")
except:
print("发送邮件失败!") send_email(file_name=sys.argv[-1]) [admin@prod.001:/mnt/nfs/oom_monitor/bin]$ cat oom_dingding.py
#!/usr/bin/env python3
import json
import requests
import datetime
import sys
def sendmessage(hostname,killed,warn_time):
now_time=datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') #替换成你自己的钉钉群的webhook
url = 'https://oapi.dingtalk.com/robot/send?access_token=917b00b5faee51bcb67e862c13b0a0ff605f0f74f4f692c9a70fe32351' HEADERS = {
"Content-Type": "application/json;charset=utf-8"
}
message='''
【OOM报警触发】:
报警主机:%s
被杀进程:%s
报警时间:%s
''' %(hostname,killed,warn_time)
String_textMsg = {
"msgtype": "text",
"text": {"content": message},
"at": {
"atMobiles": [
"110120119" # 如果需要@某人,这里写他的手机号
],
"isAtAll": 0 # 如果需要@所有人,这些写1
}
}
String_textMsg = json.dumps(String_textMsg)
res = requests.post(url, data=String_textMsg, headers=HEADERS)
print(res.text)
sendmessage(sys.argv[-3],sys.argv[-2],sys.argv[-1])

3、结果演示:

CentOS 配置OOM监控报警的更多相关文章

  1. 总zabbix配置-搭建-邮件报警-微信报警-监控mysql

    Centos7安装Zabbix4.0步骤 官方搭建zabbix4.0的环境要求: 1. 环境搭建LAMP 前提Centos系统安装完成:  确认一下: 1 2 cat /etc/redhat-rele ...

  2. 基于ELK 7.50搭建elastalert 监控报警和权限控制

    ELK+监控报警全步骤 需求: 公司要求对出在windows服务器上的日志进行日志分析并根据关键字进行报警,并配置kibana权限控制.下面为详细步骤 环境: centos 7.6 elk版本7.50 ...

  3. SQL Server监控报警架构_如何添加报警

    一.数据库邮件报警介绍 数据库邮件是从SQL Server数据库引擎发送电子邮件企业解决方案,使用简单传输协议(SMTP)发送邮件.发送邮件进程与数据库的进程隔离,因此可不用担心影响数据库服务器. 数 ...

  4. Windows Azure功能更新:弹性伸缩(autoscale)、监控报警、移动服务及网站服务商用、新的虚拟机镜像

    Windows Azure功能又更新了.此次更新包括1项重要更新和两个功能更新: 重要更新:云服务.网站支持按策略进行弹性伸缩 功能更新:两个预览版的服务(网站和移动)进入商用,虚拟机服务支持SQL ...

  5. Python-WXPY实现微信监控报警

    概述: 本文主要分享一下博主在学习wxpy 的过程中开发的一个小程序.博主在最近有一个监控报警的需求需要完成,然后刚好在学习wxpy 这个东西,因此很巧妙的将工作和学习联系在一起. 博文中主要使用到的 ...

  6. Zabbix配置邮件监控

    zabbix服务端配置 安装软件并配置 使用第三方邮件实现报警 1. 安装软件 $ yum -y install mailx 2. 配置发送邮件账号密码和服务器 $ vim /etc/mail.rc ...

  7. Kubernetes集群的监控报警策略最佳实践

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/M2l0ZgSsVc7r69eFdTj/article/details/79652064 本文为Kub ...

  8. (转)Nagios 配置及监控

    Nagios 配置及监控 原文:http://blog.csdn.net/linuxlsq/article/details/52606824 Nagios 监控 在互联网日益发展的今天,监控的重要性已 ...

  9. Ganglia与Centreon整合构建智能化监控报警平台

    一.智能运维监控报警平台的组成 随着大数据时代的来临,运维工作的难度越来越大,每个运维人员都要面临不计其数的服务器和海量的数据,如何保证众多服务器和业务系统稳定高效地运行并尽量减少死机时间,成为考核运 ...

随机推荐

  1. 矩阵快速幂-QuickPow

    矩阵快速幂引入: 1.整数快速幂: 为了引出矩阵的快速幂,以及说明快速幂算法的好处,我们可以先求整数的幂.如果现在要算X^8:则 XXXXXXXX 按照寻常思路,一个一个往上面乘,则乘法运算进行7次. ...

  2. requests模块使用二

    1.cookies和session 1.1.什么是cookie和session? cookie是网站用来辨别用户身份,进行会话跟踪,存储在本地终端上的数据. session(会话)起来本含义是指有始有 ...

  3. 目标检测 | RetinaNet:Focal Loss for Dense Object Detection

    论文分析了one-stage网络训练存在的类别不平衡问题,提出能根据loss大小自动调节权重的focal loss,使得模型的训练更专注于困难样本.同时,基于FPN设计了RetinaNet,在精度和速 ...

  4. 使用 Vue.js 改写 React 的官方教程井字棋

    React 的官方教程井字棋很好的引导初学者一步步走进 React 的世界,我想类似的教程对 Vue.js 的初学者应该也会有启发,于是使用 Vue.js 进行了改写 可以先查看最终的结果,尝试点击体 ...

  5. redis中setbit bitcount命令详解

    bitmap,位图,即是使用bit. redis字符串是一个字节序列. 1 Byte = 8 bit SETBIT key offset value 设置或者清空key的value(字符串)在offs ...

  6. Grid Illumination

    2019-07-07 16:53:31 问题描述: 问题求解: 本题和n后问题很类似,所以最初的时候就直接套了n后的板子,MLE. public int[] gridIllumination(int ...

  7. 听说用 Lombok 可以早点下班?

    听说隔壁用 Lombok 的六点就下班了,我也想六点下班! 好的,那么这篇文章就介绍下什么是 Lombok,Lombok 做了什么以及 Lombok 是怎么做的? 在介绍之前,先通过是否使用 Lomb ...

  8. R语言基本操作

    is.na and is.element is.na can use which, it finds specific rows, is.element can't, it is designed t ...

  9. 结合生活,剖析《生产者消费者模型》-java多线程(一)

    博客园的园友们好,看博客园上各位大佬的文章,已陪伴了我程序员职业的三年, 如今自己同样希望能把自己从小白到菜鸟的成长过程分享给大家.不定期更新!!! 首先我本人智商不高,理解问题十分吃力,完全不属于天 ...

  10. 通过带Flask的REST API在Python中部署PyTorch

    在本教程中,我们将使用Flask来部署PyTorch模型,并用讲解用于模型推断的 REST API.特别是,我们将部署一个预训练的DenseNet 121模 型来检测图像. 备注: 可在GitHub上 ...