Linux 内核(如下简称内核)是一个不与特定进程相关的功能集合,内核的代码很难轻易的在调试器中执行和跟踪。开发者认为,内核若是发生了错误,就不该该继续运 行。所以内核发生错误时,它的行为一般被设定为系统崩溃,机器重启。基于动态存储器的电气特性,机器重启后,上次错误发生时的现场会遭到破坏,这使得查找 内核的错误变得异常困难。html
线上的k8s集群,有时候回出现重启的现象,可是什么缘由致使重启,没法得知。node
Kdump 是一种基于 kexec 的内存转储工具,目前它已经被内核主线接收,成为了内核的一部分,它也由此得到了绝大多数 Linux 发行版的支持。与传统的内存转储机制不一样不一样,基于 Kdump 的系统工做的时候须要两个内核,一个称为系统内核,即系统正常工做时运行的内核;另一个称为捕获内核,即正常内核崩溃时,用来进行内存转储的内核。 linux
关于如何设置 kump,请参考连接:shell
https://blog.csdn.net/bytxl/article/details/45025183ubuntu
所以,线上已经部署了Kdump,用来捕捉崩溃bash
系统什么时间发生了重启?不知道。因此须要有一个脚原本监测一下,一旦发生重启,就可使用 crash分析内存转储文件服务器
在ubuntu系统中,有一个 last reboot 命令,它会显示系统重启的历史列表curl
执行命令,效果以下:ide
root@localhost:~# last reboot reboot system boot 4.4.0-119-generi Mon Jan 7 13:50 still running reboot system boot 4.4.0-119-generi Sat Jan 5 11:48 - 13:49 (2+02:01) reboot system boot 4.4.0-62-generic Sat Jan 5 10:37 - 11:47 (01:10) wtmp begins Sat Jan 5 10:37:40 2019
看姿色的文字,它排在第一行,也就是最近一次的重启记录。工具
怎么知道昨天,系统有没有重启呢?
很简单,先用 last reboot 获取最近一次的重启时间。再获取昨天的时间,将2个时间作对比,若是一致,就说明昨晚重启了,不然没有。
获取最新一次重启时间
# 最近一次重启时间 lately=`last reboot | head -1 | awk '{print $5,$6,$7}'`
昨日时间
# 昨天时间 yesterday=`date -d "-1 days" | awk '{print $1,$2,$3}'`
咱们须要构造Prometheus数据,将数据发送给Pushgateway,最后由Grafana 展现图表以及作报警
这里咱们使用shell脚原本构造数据,格式以下:
监控名{destinationName="描述信息",instance="实例,默认值为空"} 值
这些数据,我是放在一个临时文件 /tmp/check_system_restart 里面
echo "system_restart{destinationName=\"system_restart\",instance=\"$HOSTNAME\"} 1" > /tmp/check_system_restart
注意:使用因为echo外部使用了双引号,因此内部再次使用双引号时,须要使用反斜杠进行转义才行。
咱们知道,在shell里面,单引号是没法引用变量的,必须使用双引号!
$HOSTNAME 是linux 系统的一个全局变量,表示主机名
cat /tmp/check_system_restart|curl --data-binary @- http://$localIP:9091/metrics/job/system_restart_`echo $localIP | awk -F '.' '{print $NF}'`
解释:
--data-binary 参数表示 HTTP POST请求中的数据为纯二进制数据
$localIP 表示 Pushgateway的ip地址
echo $localIP | awk -F '.' '{print $NF}' 表示获取ip地址的最后一位
注意:这里的job后面跟了一段字符串,是为了保证每一台服务器发送的url不一致。这样监控数据就不会被其余主机覆盖!
关于Pushgateway 的搭建,请参考连接:
http://www.javashuo.com/article/p-yhkeybjy-ez.html
常规状况下,咱们通常使用 crontab -e 命令来添加任务计划
可是在shell脚本,却不能这么操做。
其实,直接修改 /etc/crontab 文件,也能够添加任务计划
下面一段代码,用来判断任务计划是否已经添加,不存在时,就添加!
if [ `cat /etc/crontab|grep 'check_reboot.sh'|wc -l` -eq 0 ];then cp -f /opt/check_reboot.sh /etc/ && chmod 755 /etc/check_reboot.sh echo "0 * * * * root bash /etc/check_reboot.sh" >>/etc/crontab fi
请将代码务必放到/opt目录下,由于代码路径写死了!!!
#!/bin/bash # 最近一次重启时间 lately=`last reboot | head -1 | awk '{print $5,$6,$7}'` # 昨天时间 yesterday=`date -d "-1 days" | awk '{print $1,$2,$3}'` # 判断时间是否一致 if [ "$string" == "$yesterday" ];then # 写入日志 #echo "$HOSTNAME restarted at $lately" >> /opt/restart.log echo "system_restart{destinationName=\"system_restart\",instance=\"$HOSTNAME\"} 1" > /tmp/check_system_restart else echo "system_restart{destinationName=\"system_restart\",instance=\"$HOSTNAME\"} 0" > /tmp/check_system_restart fi # 获取geteway服务器ip localIP=`ip addr | grep '192.168' | awk '{print $2}' | cut -d '/' -f 1` # 发送数据给Pushgateway if [ `cat /tmp/check_system_restart|wc -l` -ge 1 ];then cat /tmp/check_system_restart|curl --data-binary @- http://$localIP:9091/metrics/job/system_restart_`echo $localIP | awk -F '.' '{print $NF}'` else curl -X DELETE http://$localIP:9091/metrics/job/system_restart_`echo $localIP | awk -F '.' '{print $NF}'` fi # 添加任务计划 if [ `cat /etc/crontab|grep 'check_reboot.sh'|wc -l` -eq 0 ];then cp -f /opt/check_reboot.sh /etc/ && chmod 755 /etc/check_reboot.sh echo "0 * * * * root bash /etc/check_reboot.sh" >>/etc/crontab fi
执行脚本,就会自动产生 /tmp/check_system_restart 文件。
查看文件内容
root@localhost:~# cat /tmp/check_system_restart system_restart{destinationName="system_restart",instance="xx-node01"} 0
自动将脚本复制到 /etc/check_reboot.sh,这样是为了路径统一,方便添加任务计划!
最后,会自动添加任务计划!
任务计划定义的是每一个小时执行一次,为了避免等那么长时间,能够先手动执行一次 /etc/check_reboot.sh 脚本
查看 Pushgateway 数据
就会看到一条job
添加一个图形,标题叫作 昨日系统重启
设置显示的值
设置报警策略
当最后一个值等于1时,触发报警
效果以下: