乐趣区

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

背景

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

排查步骤

因为刚刚上线了新的功能,想到了配置了定时任务,可能是定时任务配置错误,导致 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 章节》

原文链接

https://tsmliyun.github.io/2019/10/16/ 一次定时任务配置错误引发的思考 /

退出移动版