Crontab实现从指定时间开始每隔多少秒(分钟/天)执行一次脚本的方法

Crontab实现从指定时间开始每隔多少秒(分钟/天)执行一次脚本的方法

背景

大家好,最近发生了很多事,已经很久没有在CSDN上推出新文章了。总之呢,我现在是一名大数据开发工程师,会从今天开始不定期地分享自己学到的新技术。如果你对大数据感兴趣的话,欢迎关注我。
最近接到了上级分配的一个任务,希望我编写一个linux的定时任务脚本,能够实现从当前时间开始每隔多少天执行一次脚本。这篇文章的故事就这么开始了~

Crontab的格式

基于这个问题,我开始百度查询关于crontab的知识,我重点讲讲我发现的crontab的局限性,在阐述我的发现之前,先让我们学习一下crontab的格式:

# Example of job definition:
# .---------------- minute (0 - 59)
# |  .------------- hour (0 - 23)
# |  |  .---------- day of month (1 - 31)
# |  |  |  .------- month (1 - 12) OR jan,feb,mar,apr ...
# |  |  |  |  .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
# |  |  |  |  |
# *  *  *  *  * user-name command to be executed
  1. minute: 区间为 0 – 59
  2. hour: 区间为0 – 23
  3. day-of-month: 区间为0 – 31
  4. month: 区间为1 – 12. 1 是1月. 12是12月.
  5. Day-of-week: 区间为0 – 7. 周日可以是0或7.

Crontab可以说是一款非常优秀的定时启动任务工具,可以让我们指定每隔多少分钟、多少小时、多少天、几个月或者每个星期的星期几来执行任务。

Crontab的使用与局限性

再优秀的工具都有其局限性,在我使用Crontab的过程当中,我发现在指定不同的时间间隔时,Crontab都有其局限性:

  1. minute: 只可以以一个小时为范围来指定间隔多少分钟。
  2. hour: 只可以以一天为范围来指定间隔多少小时。
  3. day-of-month: 只可以以一个月为范围指定间隔多少天。
  4. month: 只可以以一年为范围指定间隔几个月。

我上面的阐述可能不太易于理解,没关系,让我们结合具体实例来讲解:

  1. 每隔7分钟运行一次命令:
    */7 * * * * /root/bin/check-status.sh
    比如说我在今天的10:05分开启了这个定时任务,我的本意是希望这个定时任务是从当前时间开始每隔7分钟执行。但是事实上不是的,crontab的分钟任务是以一个小时为单位和范围的,也就是该任务会在10:07分第一次执行,并每隔7分钟执行一次,待10:56分的这一次执行完成后,下一次并不会在11:03分执行,而是会每隔一小时重新刷新计时,所以下一次会在11:00分执行,再在11:07分执行,以此反复。这就会导致在两个小时的交界处任务的频繁执行,同时,如果我希望任务每隔61分钟执行一次,目前的crontab也无法很好解决。
  2. 每隔10小时运行一次命令:
    0 */10 * * * /root/bin/check-status.sh
    比如说我在今天的9:00 am开启了这个定时任务,我的本意是希望这个定时任务是从当前时间开始每隔10小时执行。但事实上不是的,crontab的小时任务是以一天为单位和范围的,也就是该任务会在10:00 am第一次执行,并每隔10小时执行一次。待20:00pm的这一次执行完成后,由于在等待下一次的执行的过程中,时间来到了两天的交界处,因此定时任务会被重新刷新。也就是下一次任务会在第二天的00:00 am时执行,然后再在10:00am执行,以此反复。这就会导致在两天的交界处任务的频繁执行,同时,如果我希望任务每隔25小时执行一次,目前的crontab也无法很好解决。
  3. 每隔8天运行一次命令:
    0 0 */8 * * /root/bin/check-status.sh
    比如说我在1月的6日开启了这个定时任务,我的本意是希望这个定时任务是从今日开始每隔8日执行。但事实上不是的,crontab的天任务是以一个月为单位和范围的,同时又由于每个月的起始值是1日,也就是该任务会在9日的零时零分第一次执行,然后在17日、25日的零时零分分别执行一次。再之后就到了两个月的交界处,该定时任务会被重新刷新,也就是下一次任务会在2月1日的零时零分执行,以此反复。这就会导致在两个月的交界处任务的频繁执行,同时,如果我希望任务每隔32天执行一次,目前的crontab也无法很好解决。
  4. 每隔5个月执行一次命令:
    0 0 1 */5 * /root/bin/check-status.sh
    比如说我在2020年4月1日开启了这个定时任务,我的本意是希望这个定时任务从本月开始每隔5个月执行。但事实上不是的,crontab的月任务是以一年为单位和范围的,同时又由于每年的起始值是1月,也就是该任务会在6月1日的零时零分第一次执行,然后在11月1日的零时零分执行一次。再之后就到了两年的交界处,该定时任务会被重新刷新,也就是下一次任务会在2021年的1月1日的零时零分执行,以此反复。这就会导致在两年的交界处任务的频繁执行,同时,如果我希望任务每隔13个月执行一次,目前的crontab也无法很好解决。

解决方法

基于以上crontab存在的局限性和我的需求(需指定从当前时刻开始每隔多少时间执行一次任务),我摸索了一阵子之后,得到了一个不太华丽的解决办法,但是可以帮助广大网友们在时间短、任务重的情形之下应急使用。
解决办法同样是在/etc/cron.d/下编写一个定时启动脚本(crontab方面的基础网上都有,请码友们自行补充学习),只是我们的代码略为复杂。脚本内容如下:

SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=""
lastRunTime=1611803325
seconds=120

*/1 * * * * root source /etc/profile && intervalRunTime=$[ (`date +\%s` - $lastRunTime) \% $seconds ] && if [( $intervalRunTime -ge 0 ]] && [[ $intervalRunTime -lt 60 ]];then echo $intervalRunTime>>$HOME/crontab.log; fi

通过观察以上我编写的代码,大家可以发现我是通过将当前时间绝对秒数作为初始声明变量赋予lastRunTime变量,然后再将间隔时间的秒数(若是间隔2分钟就是120秒,间隔1小时就是3600秒)作为初始声明变量赋予seconds变量。
之后,每隔一分钟定时任务脚本就会判断intervalRunTime(当前时间绝对秒数-lastRunTime)是否大于等于0并且小于60,若满足条件,则echo i n t e r v a l R u n T i m e > > intervalRunTime>> intervalRunTime>>HOME/crontab.log(码友们可以将这部分修改为你们自己需要执行的任务)。
之所以判断条件是大于等于0并且小于60,是因为crontab的最小间隔时间为1分钟,因此将定时任务在每隔seconds后的那一分钟内执行一次。

我的解决办法仍不够优雅,希望码友们如果想到了更好的解决办法或者有什么疑问的话,欢迎在评论区讨论~

  • 7
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LebronChen666

感谢码友们的支持~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值