crontab导致CPU异常的问题分析及处理

今天查看数据库负载没有发现问题,但是当我使用top命令的时候,发现有一个进程占用了大量的cpu资源而且已经执行很长时间了。这一下子引起了我的注意。
  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND  
25807 oraccbs1  25   0  8728  732  564 R 100.0  0.0   2021:19 /bin/sh -c /opt/app/oracle/xxxxxx/Script/DailyChk/chk_path_full.ksh PRODB 2>&1 >/opt/app/oracle/Script/DailyLog/chk_path_full.log 
13578 oraccbs1  18   0 40.2g  49m  29m D 61.0  0.0   6:40.18 oraclePRODB (LOCAL=NO)
17085 oraccbs1  18   0 40.2g  48m  24m R 40.6  0.0  36:44.43 oraclePRODB (LOCAL=NO)
30894 oraccbs1  18   0 40.3g  56m  27m D 38.1  0.0  54:40.46 oraclePRODB (LOCAL=NO) 
10616 oraccbs1  18   0 40.3g  54m  24m R 36.8  0.0  28:15.49 oraclePRODB (LOCAL=NO)
17089 oraccbs1  18   0 40.2g  49m  25m R 36.8  0.0  60:11.90 oraclePRODB (LOCAL=NO)
12103 oraccbs1  18   0 40.2g  31m  22m R 35.6  0.0 149:38.06 oraclePRODB (LOCAL=NO)
30898 oraccbs1  18   0 40.2g  50m  32m D 35.6  0.0  56:03.90 oraclePRODB (LOCAL=NO)

对于这个脚本我比较陌生,一般这些维护性的工作主要都是客户来做的。尝试查看了下这个脚本的内容,发现是一个检测脚本,
脚本的内容很清晰,是来监控归档目录和home目录的空间使用情况,当超过阀值的时候,就发送短信给响应的人来处理。
内容大体如下:
#Send Short Message  if %used greater than 80% : ARCHIVE
        PERC_ARCH_USED=`df -P ${ARCH_PATH}|awk '{ print $5 }'|grep "%"|tr -d "%"`
        export casename=`uname -n`_${database}_Percent_Archive_Used_IS_${PERC_ARCH_USED}
        if [[ $PERC_ARCH_USED -gt 80 ]]; then
        sqlplus -s xxxxx @$myDir/Sql/sendsms.sql $casename
        fi

#Send Short Message  if %used greater than 80% : $ORACLE_HOME
        PERC_HOME_USED=`df -P ${HOME_PATH}|awk '{ print $5 }'|grep "%"|tr -d "%"`
        export casename=`uname -n`_${database}_Percent_HOME_Used_IS_${PERC_HOME_USED}
        if [[ $PERC_HOME_USED -gt 80 ]]; then
        sqlplus -s xxxxxx @$myDir/Sql/sendsms.sql $casename
        fi

这样一个脚本的执行肯定执行一次就完了。它是从哪里执行的呢,首先想到的就是crontab。
crontab是在系统级作为作业自动执行的利器,可以进行各种细粒度的配置,使用也很方面。
先来查看一下crontab的情况,结果在crontab的最后发现一个配置就是正在执行的job.
>crontab -l
#------------------------------------------------
# Test Log DB for house keeping .....
#------------------------------------------------
#0,30 * * * * /opt/app/oracle/xxxxxx/Script/DailyChk/chk_path_full.ksh PRODB 2>&1 >/opt/app/oracle/Script/DailyLog/chk_path_full.log 

这样来看似乎问题找到了原因,但是奇怪的是根据crontab里面的设置,这个job已经被禁用了,怎么还在运行?
毕竟这个问题还不能完全肯定是操作问题还是其他的原因导致的,就先不轻率的决定,把问题分给客户,从我的角度来说,怎么才能得到一些信息来说明这个问题才是关键。
首先是crontab的执行频率问题。如果没有接触过crontab可能会有些陌生。
crontab命令包含6个参数,命令的一些基本说明如下:

*      *   *   *   *  command
  分   时  日  月  周   命令

  第1列表示分钟1~59 每分钟用*或者 */1表示
  第2列表示小时1~23(0表示0点)
  第3列表示日期1~31
  第4列表示月份1~12
  第5列标识号星期0~6(0表示星期天)
  第6列要运行的命令

在这个例子中。0,30是第一个参数,就代表每个小时的0分,30分执行一次下面的脚本。
0,30 * * * * /opt/app/oracle/xxxxxx/Script/DailyChk/chk_path_full.ksh PRODB 2>&1 >/opt/app/oracle/Script/DailyLog/chk_path_full.log
如果要求脚本在指定的时间段,比如只在5分,20分,30分的时候执行,
5,20,30 * * * * /opt/app/oracle/xxxxxx/Script/DailyChk/chk_path_full.ksh PRODB 2>&1 >/opt/app/oracle/Script/DailyLog/chk_path_full.log

如果要求脚本在指定的时间段,比如只在每天晚上的11:30执行,就可以写成下面的形式。

30 23 * * * /opt/app/oracle/xxxxxx/Script/DailyChk/chk_path_full.ksh PRODB 2>&1 >/opt/app/oracle/Script/DailyLog/chk_path_full.log

从配置来看,job是每隔半个小时执行一次,而且所做的检查工作也不复杂,执行时间应该会很短。配置中这个job已经被禁用,如果我们能够证明这个job是通过crontab执行的就能够说明是操作问题。因为crontab里面已经禁用,但是实际上job还在运行。
通过进程的信息,我们知道这个进程已经执行了近2021分钟,我们来推算一下执行的时间。2021/60=33个小时,从下午3点往前推33个小时,就是在29号早晨的7点左右开始执行的。
  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND                                                                                                                                                                       
25807 oraccbs1  25   0  8728  732  564 R 100.0  0.0   2021:19 /bin/sh -c /opt/app/oracle/xxxxxx/Script/DailyChk/chk_path_full.ksh PRODB 2>&1 >/opt/app/oracle/Script/DailyLog/chk_path_full.log 

这个时候日志就是最好的证明工具,可以在/var/spool/mail/oraccbs1下面找到相应的日志。
日志中最近的一次执行时间是在昨天的早晨7:30,之后就没有任何相关的日志了。
Mon Dec 29 07:30:01 2014
Return-Path:
Received: from localhost.localdomain (xxxxx[127.0.0.1])
        by localhost.localdomain (8.13.8/8.13.8) with ESMTP id sBT0U1mr013412
        for ; Mon, 29 Dec 2014 07:30:01 +0700
Received: (from oraccbs1@localhost)
        by localhost.localdomain (8.13.8/8.13.8/Submit) id sBT0U1Jh013347;
        Mon, 29 Dec 2014 07:30:01 +0700
Date: Mon, 29 Dec 2014 07:30:01 +0700
Message-Id:
From: root@localhost.localdomain (Cron Daemon)
To: oraccbs1@localhost.localdomain
Subject: Cron  /opt/app/oracle/xxxxxx/Script/DailyChk/chk_path_full.ksh PRODB 2>&1 >/opt/app/oracle/Script/DailyLog/chk_path_full.log
Content-Type: text/plain; charset=UTF-8
Auto-Submitted: auto-generated

/bin/sh: fork: Resource temporarily unavailable

From oraccbs1@localhost.localdomain  Mon Dec 29 07:30:05 2014
。。。。
得到了这些基本信息,就能够基本确定问题了。
至于crontab的修改,可以使用crontab -e来完成。感觉就跟vi操作一样。客户做了确认之后,手工kill掉了那个job,那个问题就解决了。
有很多朋友反馈说为什么会导致CPU异常,因为问题已经修复了,我就从支离破碎的日志中做了简单的分析。
可以通过上面的日志看到fork: Resource temporarily unavailable这个问题,说明在执行crontab job的时候发生了问题,这个问题可能是数据库中其它的资源消耗导致的,也可能是发送消息的环节导致的,因为发送消息的细节是客户来维护,他们不愿意透露更多的细节,我们只能做主观上的猜测了。
不过通过下面的日志能够得到一些信息。就是crontab的job很可能是个僵尸进程。存在两个相同的进程。
>ps -ef|grep DailyChk

oraccbs1 14187  7786  0 14:59 pts/10  
00:00:00 grep DailyChk

oraccbs1 25793     1  0 Dec29
?        00:00:00 /bin/sh -c /opt/app/oracle/xxxxxx/Script/DailyChk/chk_path_full.ksh PRODB 2>&1 >/opt/app/oracle/Script/DailyLog/chk_path_full.log

oraccbs1 25807 25793 99 Dec29
?        1-09:58:51 /bin/sh -c /opt/app/oracle/xxxxxx/Script/DailyChk/chk_path_full.ksh PRODB 2>&1 >/opt/app/oracle/Script/DailyLog/chk_path_full.log

最后从昨天的top截图中发现了如下的内容,可以基本断定问题是crontab 的那个job成为了僵尸进程导致的。
Tasks: 7196 total,  26 running, 7165 sleeping,   0 stopped,   5 zombie
Cpu(s):  7.8%us,  1.5%sy,  0.0%ni, 90.1%id,  0.1%wa,  0.1%hi,  0.4%si,  0.0%st
Mem:  363033360k total, 116349772k used, 246683588k free,  2176616k buffers

时间: 2024-09-02 16:38:25

crontab导致CPU异常的问题分析及处理的相关文章

服务器进程异常的原因分析(第二篇)

最近看到一个报警,是显示某一个oracle的备库进程数达到了2000多个.ZABBIX-监控系统: ------------------------------------报警内容: Too many OS processes on ora_xxx@10.127.13.123 ------------------------------------报警级别: PROBLEM ------------------------------------监控项目: Number of processes

Linux主机肉鸡木马minerd导致CPU跑满

Linux主机挖矿木马minerd导致CPU跑满 [问题现象] Linux主机CPU跑满,或者使用服务器越来越慢,以及收到报警信息提示服务器有对外恶意扫描. 这个现象的第一反应就是服务器被黑了,遇到这种情况首先要做的是对服务器进行一下数据备份,通过阿里云的快照备份功能是可以快速的实现对服务器以及系统内部数据的备份的. [问题原因] 这种状况在出现时通过top命令可以看到有一个minerd进程占用CPU较高. 经定位,该进程是一个挖矿程序,通过上述截图可以看到进程对应的PID为1170,根据进程I

【故障处理】序列cache值过小导致CPU利用率过高

[故障处理]序列cache值过小导致CPU利用率过高 1  BLOG文档结构图       2  前言部分 2.1  导读和注意事项 各位技术爱好者,看完本文后,你可以掌握如下的技能,也可以学到一些其它你所不知道的知识,~O(∩_∩)O~: ① enq: SQ - contention等待事件的解决 ② 一般等待事件的解决办法 ③ DFS lock handle等待事件 ④ 与序列有关的等待事件   Tips: ① 本文在ITpub(http://blog.itpub.net/26736162)

不正当使用HashMap导致cpu 100%的问题追究

因最近hashmap误用引起的死循环又发生了一些案例,左耳朵浩子写了一篇blog 疫苗:Java HashMap的死循环,看了一下,大家的分析如出一辙.这篇blog也是好几年前写的了,之前在平台技术部的博客上贴过,随着组织结构的调整,那个博客可能不再维护,把这篇文章在这儿也保存一下. 李鹏同学在blog里写了篇关于HashMap死锁模拟的文章: http://blog.csdn.net/madding/archive/2010/08/25/5838477.aspx 做个纠正,那个不是死锁问题,而

快速找出php中可能导致cpu飙升问题的代码行

用cpu接近100%时,你如何找到导致cpu飙升的原因?我的思路是,首先找到进程正在执行的代码行,从而确定可能有问题的代码段.然后,再仔细分析有问题的代码段,从而找出原因. 如果你的程序使用的是c.c++编写,那么你可以很容易的找到正在执行的代码行.但是,程序是php编写的,如何找到可能有问题的代码行呢?这个问题就是本文要解决的问题. 背景知识: 大家都知道php是一个解释性语言.用户编写的php代码会生成opcode,由解释器引擎去解释执行.在解释执行过程中,有一个全局变量包含了执行过 程中用

android播放器加载时候按返回导致ANR异常,求大神

问题描述 android播放器加载时候按返回导致ANR异常,求大神 我自己写的一个android播放器,滑动屏幕进行快进,然后视频处于加载的时候,点击返回按钮,就会出现ANR异常.求解,想了好久了,求大神相救.不胜感激 03-10 13:18:44.878: E/mdb_debug(350): mdb_usb_sharenet.c:send_sharenet_msg[L-232]: mdb usb share net channel is not ready!: 0, Success 03-10

iptables防火墙规则导致端口不通的案例分析

iptables防火墙规则导致端口不通的案例分析 问题现象: 一台服务器的8080端口访问不通,但其他端口正常,例如ssh的22端口,ping也正常. 从其他机器上进行telnet连接8080端口测试,显示是下边这个结果. [root@iZ25a9b7bpcZ ~]# telnet xx.xx.xx.xx 8080 Trying xx.xx.xx.xx... telnet: connect to address xx.xx.xx.xx: No route to host 从telnet测试的结果

SQLSERVER 导致CPU 100%怎么解决!

问题描述 网站10分钟内同时在线3500人,导致CPU100%.服务器X3330CPU.4G内存是不是数据库结构的还是SQLSERVER的优化没做好?求助 解决方案 解决方案二:有可能,或者用多台sqlserver做cluster?解决方案三:引用1楼findcaiyzh的回复: 有可能,或者用多台sqlserver做cluster? UP解决方案四:换CPU!解决方案五:对sql语句优化减少cpu占用时长换个强大的cpu或者考虑多服务器集群模式集群我没用用过但集群可以解决这个问题解决方案六:用

外接程序VMDebugger未能加载或导致了异常

  故障现象:打开Visual Studio 2010后弹出错误框,外接程序VMDebugger未能加载或导致了异常,是否希望移除该外接程序,错误号:80004005.系统版本:WIN8.1 64位企业版,安装了Resharper8.1,破解. 解决办法:修改下注册表文件解决. HKEY_LOCAL_MACHINESOFTWAREWow6432NodeMicrosoftVisualStudio10.0AddInsVMDebugger.Connect LoadBehavior项改为0 然后打开vs