crontab在一秒内刷新屡次致使部分脚本不生效的问题分析

版权声明:本文由康中良原创文章,转载请注明出处: 
文章原文连接:https://www.qcloud.com/community/article/182mysql

来源:腾云阁 https://www.qcloud.com/communitysql

 

今天ob在几台DB上发现crontab中的监控任务,历来没有执行。但操做一下crontab的配置crontab –e + wq,监控任务就能正常执行,重启cron也能正常执行。函数

出问题的机器crontab的状况以下:

问题挺奇怪,第一条crontab执行正常,第二条crontab一直没有执行。spa

第一条正常,证实cron有正常运行。DB监控任务的crontab是凯丽系统自动安装的,理论上不会存在忽然出错的状况。日志

问题定位:

cron出bug了? 第二个任务确实没有执行,仍是执行前遇到问题退出,恰好日志又打印到/dev/null了..code

考虑到crontab执行历史在系统日志里会有记录,检查var/log/message日志以下,整*/5的分钟点只有crontab的第一个任务。crontab

crontab第二个任务确实没执行,应该是crontab出了点问题,再看看在修改crontab的那一刻发生了什么?文档

根据crontab最后一次修改的时间(2012-06-18 17:51:01),检查系统日志以下:
get

刚巧,在同一秒内修改了2次crontab。根据凯丽安装监控的顺序,第一个crontab应该是在安装第一条crontab任务,第二个crontab应该是在安装第二个crontab任务。it

猜测:根据cron的工做原理,难道在增长第一个任务以后,cron加载了crontab的配置(/var/spool/cron/tabs/mysql),可是在增长第二个任务以后,cron没有加载该配置? 若是是这样,那么cron判断是否须要加载配置文件的机制是如何的呢?

网上文档稀少,直接看代码。

在网上找到一个debian的cron源代码: cron_3.0pl1.orig.tar.gz

解压打开,查看cron的执行过程:
在cron.c 的main函数中,cron的主函数代码以下:

cron_sleep(): crontab 最小执行单位是分钟,所以是每60秒执行一次.TargetTime += 60;

load_database(): 检查crontab的配置文件是否有更新,若是有更新,则从新load,不然使用上次记录的database cron_tick( ): 实际执行任务查看cron是如何加载crontab的配置文件的,进入load_database()函数.
database.c :

能够看到,在cron加载配置的时候,会先获取/var/spool/cron/tabs 目录stat信息,而后获取用户的crontab配置文件的stat信息,而后比较上一次统计的修改时间与tabs目录、crontab配置文件的最后修改时间,若是一致则不从新load,不然从新load crontab配置文件。

stat为系统函数调用,该函数取得的结构体的st_mtime的单位为秒。

至此,咱们能够得出这样的结论:

因为两次crontab修改时间均在同一秒,而cron的加载是以crontab配置文件的最后修改时间(秒级)来判断文件是否须要更新。当出现如下场景,第二次对crontab的修改就会失效(不只是增长)。

crontab失效的场景:

而这个场景,恰好是咱们的DB出现crontab失效的状况。

crontab的刷新机制,是以crontab文件的最后修改时间为准.

所以,若是在一秒内对crontab进行屡次(大于1次)操做,就可能出现后修改的crontab不执行!

当再次对crontab文件进行保存操做时,cron会从新加载配置文件,crontab生效.

解决办法:

该问题是因为在一秒内执行屡次crontab变动致使。所以解决办法有3个:

  1. 在凯丽每次操做crontab的时候增长sleep 1的操做

  2. 在凯丽每次crontab操做完成以后,sleep 1,强制刷新crontab的最后更新时间

  3. 合并并行的crontab操做为一次操做,减小对crontab的操做频率

根据凯丽的状况,选择第二个方案对现有代码改动最小。

提醒:

脚本尽可能不要在同一秒内屡次操做crontab内容,不然可能致使crontab不生效的状况。

相关文章
相关标签/搜索