如何配置使crontab任务允许重叠执行?
看起来你的问题出在crond本身的默认行为上——大多数常见的crontab实现(比如vixie-cron、dcron)都会默认限制:同一个用户的同一条cron任务,如果当前还有实例在运行,就不会触发新的执行。这就是为什么你的task2在14:54启动后,因为sleep了90秒,14:55的时候进程还没结束,所以crond直接跳过了那一分钟的task2,直到14:56进程结束后才重新执行。
下面给你几个可行的解决方案:
方案1:让任务后台执行(无需更换cron)
最简单的办法是把你的长耗时任务改成后台运行,这样crond会认为任务已经执行完成,下一分钟就会正常启动新的实例。
比如修改你crontab里的task2条目:
* * * * * (echo "[task2] $(date +\%H:\%M:\%S)" >> /tmp/cron.log && sleep 90) &
用括号把命令包起来,最后加&让它在后台运行,crond启动这个子进程后会立刻退出,不会再跟踪后台的sleep进程,这样下一分钟的task2就能正常触发了。
如果任务逻辑更复杂,建议把它放到单独的脚本文件里,比如创建/usr/local/bin/run_task2.sh:
#!/bin/bash echo "[task2] $(date +%H:%M:%S)" >> /tmp/cron.log sleep 90
给脚本加执行权限:chmod +x /usr/local/bin/run_task2.sh,然后crontab里改成:
* * * * * /usr/local/bin/run_task2.sh &
这样更清晰,也方便后续维护。
方案2:更换支持并发的cron实现
如果你的需求是让所有任务都默认允许重叠,或者需要更精细的并发控制,可以换成fcron——这是一个专门支持任务并发、还能处理错过的任务的cron工具。
- 先安装fcron(不同系统包管理器不同,比如Debian/Ubuntu用
apt install fcron,CentOS/RHEL用yum install fcron) - 修改你的
cronjobs.sh脚本,把启动命令换成fcron:
#!/bin/bash set -e exec fcron -f
- 重启supervisord让配置生效:
supervisorctl restart crond
fcron默认不会限制同任务的并发执行,完全符合你的需求,而且它还支持更多高级特性,比如任务优先级、错过任务的补执行策略等。
注意事项
不管用哪种方案,都要留意系统资源占用——如果任务执行时间长、每分钟都启动新实例,可能会导致系统进程过多、CPU/内存负载过高,最好根据实际情况评估是否需要加一些并发控制(比如用flock限制最大实例数,但这和你要的“允许重叠”需求相反,仅作提醒)。
备注:内容来源于stack exchange,提问作者pablorsk

