crontab定时任务设置超时、互斥
crontab定时任务设置超时、互斥
ivansli线上业务经常会用到邮件系统,假设在没有使用异步消息队列(最常用的方式)处理的情况下,使用php脚本+crontab定时任务(每分钟启动一次)来发送邮件,都需要考虑什么情况呢?
定时任务执行超时
crontab定时任务设为每分钟启动一次,如下:
1 | * * * * * php /root/php/cron.php |
问题:如果这脚本出现异常,进程僵死怎么办?
假设由于未知因素,cron.php 脚本一直执行,没有退出。极端情况,进入一个死循环。原来说好的一分钟执行一次,现在后面的脚本也不能跑了。
解决办法:使用timeout设置脚本执行超时时间
1 | * * * * * timeout 120 php /root/php/cron.php >> /root/php/logs.log 2>&1 |
上面定时任务脚本最大执行时间120秒,超过120秒之后进程就会退出,这样就可以解决僵死的情况。
定时任务进程互斥
问题:
由于设置的定时任务是每分钟启动一次,在未来的某个时刻就会出现多个脚本进程在执行相同任务,此刻可能就会造成数据的不一致性等问题。那么,该怎么避免呢?
解决办法:
使用 flock 设置文件锁来进行互斥控制。
1 | 用法: |
文件锁互斥参数为 flock -xn, 同时设置互斥文件 /tmp/cron1.lock。
1 | * * * * * flock -xn /tmp/cron1.lock -c "timeout 120 php /root/php/cron.php" |
为了方便排查,把输出数据追加到指定日志文件中。
1 | * * * * * flock -xn /tmp/cron1.lock -c "timeout 120 php /root/php/cron.php >> /root/php/logs.log 2>&1" |
定时任务执行频率提升
问题:
觉得一分钟启动一次频率太低,想10s启动一次怎么办?
解决办法:
添加多个相同定时任务,每个定时任务sleep指定时间之后执行。
1 | * * * * * php /home/app/email.php >> /home/log/test.log 2>&1 |
定时任务互斥及超时验证
用于测试的php脚本
1 |
|
添加crontab定时任务
1 | * * * * * flock -xn /tmp/cron1.lock -c "timeout 120 php /root/php/cron.php >> /root/php/logs.log 2>&1" |
查看日志文件/root/php/logs.log发现会有数值不停输出,120秒左右之后数值暂停输出。此时使用ps -aux | grep php查看没有发现定时任务相关的进程信息,说明timeout 120起到了作用。然后,等待若干秒,等下一分钟的第一秒到达时,会发现数值又开始输出,也可以看到对应的定时任务进程信息,如此往复。
1 | 9999 |
定时任务执行期间,若再打开另外一个终端,手动在命令行执行:
1 | flock -xn /tmp/cron1.lock -c "timeout 120 php /root/php/cron.php >> /root/php/logs.log 2>&1" |
结果:
① 命令行执行命令由于没有获得锁,直接退出(因为 flock 互斥)
② 定时任务执行120 秒后自动由于超时退出进程(因为 timeout 120),此时再手动在命令行执行则可以成功