一次定时任务配置错误引发的思考


背景

某业务人员反应系统登陆不上去,于是程序员自己试着登陆系统成功了,心里很自信的认为“我的代码没有问题”,便让业务人员再试试。然后业务人员是登陆成功了,但是整个系统用起来很卡,这下程序员意识到是系统的问题了。

排查步骤

因为刚刚上线了新的功能,想到了配置了定时任务,可能是定时任务配置错误,导致PHP启了过多进程。

使用命令ps -ef | grep php 查看,果然是起了很多没必要的更新数据脚本,其中涉及到与第三方接口的交互并且有大量的更新数据库的操作,所以直接导致系统卡顿。

使用命令crontab -l查看crontab配置,有几个脚本的执行频率是想配置成每小时执行一次,结果配置错误,导致每分钟执行一次。具体如下:

# 错误配置
* */1 * * * /usr/local/bin/php /data/site/demo/yii demo/sync-product

# 正确配置
0 */1 * * * /usr/local/bin/php /data/site/demo/yii demo/sync-product

问题是排查到了,现在需要做的就是快速kill掉那些没必要的进程。这时候便想到了万能的awk命令,如下:

ps -ef | grep php | awk '{print $2}' | xargs kill -9

执行后,系统开始恢复稳定。

思考

整个问题排查总结下来,归根结底还是配置crontab是不够细心。

同时也引发了其他的一些思考,总结后整理如下:

系统突然出现卡顿,常用的排查思路有哪些呢?

  1. 查看内存使用状况:free -g
  2. 查看磁盘使用状况:df -h
  3. 查看磁盘I/O使用:iostat -dx
  4. 查看CPU使用:top

具体的系统调优,本文不做介绍了。

awk命令的基本使用

常用命令

awk '条件类型 1{动作1} 条件类型2{动作2} ...' filename

awk后面接两个引号并加上大括号来设置想要对数据进行的处理动作。

例如:我们要取出账号与登录者的IP,且之间以[TAB]隔开,则:

[release@api_02 ~]$ last -n 5 | awk '{print $1 "\t" $3}'
release	117.111.111.11
release	117.111.111.11
release	117.111.111.11
release	117.111.111.11
release	117.111.111.11

awk还存在一些内置变量

变量名称 代表意义
NF 每一行拥有的字段总数
NR 目前awk处理的是第几行
FS 目前的分隔符,默认为空格键

继续上面的例子,需求为:

  • 列出每一行的账号
  • 列出目前处理的行数
  • 说明该行有多少字段
[release@api_02 ~]$ last -n 5 | awk '{print $1 "\t lines:" NR "\t columns:"NF}'
release	 lines:1	 columns:10
release	 lines:2	 columns:10
release	 lines:3	 columns:10
release	 lines:4	 columns:10
release	 lines:5	 columns:10

awk命令还有更多高级的功能,此处就不做介绍了。

crontab配置的基本使用

crontab配置的规则是:

minute   hour   day   month   week   command

其中每个字段的含义如下:

minute: 分钟,取值范围:0-59之间的整数

hour:小时,取值范围:0-23之间的整数

day:日期,取值范围:1-31之间的整数

month:月份,取值范围:1-12之间的整数

week:星期几,取值范围:0-7之间的整数,这里的0或7代表星期日

command:要执行的命令,可以是系统命令,也可以是自己编写的脚本文件。

特殊字符:

星号(*):表示所有值

逗号(,):可以用逗号隔开的值指定一个列表范围,例如,“1,2,6,7”

中杠(-):可以用整数之间的中杠表示一个整数范围,例如“1-3”表示“1,2,3”

正斜线(/):可以用正斜线指定时间的间隔频率,例如“0-23/2”表示每两小时执行一次。同时正斜线可以和星号一起使用,例如*/10,如果用在minute字段,表示每十分钟执行一次。

常用的一些例子

实例1:每1分钟执行一次command
命令:
* * * * * command
 
实例2:每小时的第3和第15分钟执行
命令:
3,15 * * * * command
 
实例3:在上午8点到11点的第3和第15分钟执行
命令:
3,15 8-11 * * * command
 
实例4:每隔两天的上午8点到11点的第3和第15分钟执行
命令:
3,15 8-11 */2 * * command
 
实例5:每个星期一的上午8点到11点的第3和第15分钟执行
命令:
3,15 8-11 * * 1 command
 
实例6:每晚的21:30重启smb 
命令:
30 21 * * * /etc/init.d/smb restart
 
实例7:每月1、10、22日的4 : 45重启smb 
命令:
45 4 1,10,22 * * /etc/init.d/smb restart
 
实例8:每周六、周日的1 : 10重启smb
命令:
10 1 * * 6,0 /etc/init.d/smb restart
 
实例9:每天18 : 00至23 : 00之间每隔30分钟重启smb 
命令:
0,30 18-23 * * * /etc/init.d/smb restart

参考资料

linux卡顿怎么排查

《Linux鸟哥的私房菜基础学习第三版–12.4.2章节》