如何安排每个月的第一个星期日运行
Posted
技术标签:
【中文标题】如何安排每个月的第一个星期日运行【英文标题】:How to schedule to run first Sunday of every month 【发布时间】:2011-03-15 12:59:06 【问题描述】:我在 RedHat 上使用 Bash。我需要安排一个 cron 作业在每个月的第一个星期日上午 9:00 运行。我该怎么做?
【问题讨论】:
【参考方案1】:您可以在crontab
文件中添加这样的内容:
00 09 * * 7 [ $(date +\%d) -le 07 ] && /run/your/script
date +%d
为您提供当天的编号,然后您可以检查该天是否小于或等于 7。如果是,请运行您的命令。
如果您只在星期日运行此脚本,则应该意味着它只在每月的第一个星期日运行。
请记住,在 crontab
文件中,date
命令的格式选项应该被转义。
【讨论】:
这太棒了-le
的东西记录在哪里?我需要为第 1 个星期日、第 2 个星期日、第 3 个星期日、第 4 个星期日和(也许)第 5 个星期日做同样的事情......
与test
命令相同(这些是这些命令的快捷方式):linux.die.net/man/1/test【参考方案2】:
值得注意的是,看起来最明显的解决此问题的方法不起作用。
您可能认为您可以只编写一个 crontab 条目,将星期几指定为 0(表示星期日),将月份指定为 1-7,如下所示...
# This does NOT work.
0 9 1-7 * 0 /path/to/your/script
...但是,由于an eccentricity of how Cron handles crontab lines with both a day-of-week and day-of-month specified,这将不起作用,实际上会在每月的 1 号、2 号、3 号、4 号、5 号、6 号和 7 号运行(无论是哪一天)他们所在的星期)和在每个月的每个星期日。
这就是为什么您看到建议使用 [ ... ]
检查和 date
来设置这样的规则 - 在 crontab 中指定星期几并使用 [
和 date
在运行脚本之前检查月份是否为 accepted answer 所示,或在 crontab 中指定月份范围并使用 [
和 date
来检查日期运行前一周,如下所示:
# This DOES work.
0 9 1-7 * * [ $(date +\%u) = 7 ] && /path/to/your/script
如果您想确保您的 crontab 行无论您使用的是什么操作系统,请记住一些最佳实践:
使用=
,而不是==
,进行比较。它更便携,因为并非所有 shell 都使用支持 ==
运算符的 [
实现。
使用%u
说明符到date
将星期几作为数字,而不是%a
运算符,因为%a
会根据运行date
的语言环境给出不同的结果.
只需使用date
,而不是/bin/date
或/usr/bin/date
,因为date
实用程序在不同系统上的位置不同。
【讨论】:
这种方法每个月触发7次检查,6次什么都不做。每个星期天检查一天是否最多为 7 的方法每月触发检查 4 到 5 次,3 到 4 次什么都不做。因此,后一种方法效率更高。此外,它仅在您可以更轻松地负担开销的星期天触发。承认,这在实践中可能没有任何区别......【参考方案3】:您需要结合两种方法:
a) 使用cron
在每周日上午 9:00 运行作业。
00 09 * * 7 /usr/local/bin/once_a_week
b) 在once_a_week
的开头,通过shell、Python、C/C++、...计算日期并提取月份中的某天,并测试1 到7 之间(含)。如果是,执行真正的脚本;如果没有,请静默退出。
【讨论】:
两者都像man 5 crontab
所说的那样工作 day of week 0-7 (0 or 7 is Sun, or use names)
你说得对,我检查了 man crontab(没说太多),但没有检查 man 5 crontab,它解释了 0 和 7 都算作星期日。【参考方案4】:
一个 hacky 解决方案:让您的 cron 作业每周日运行,但让您的脚本在开始时检查日期,如果当月的日期大于 7 则立即退出...
【讨论】:
【参考方案5】:这也适用于工作日的名称:
0 0 1-7 * * [ "$(date '+\%a')" == "Sun" ] && /usr/local/bin/urscript.sh
但是,
[ "$(date '+\%a')" == "Sun" ] && echo SUNDAY
由于在 crontab 中对“%”的特殊处理,将在命令行上FAIL(也适用于https://***.com/a/3242169/2919695)
【讨论】:
这与上面的类似,但我更喜欢它的可读性。 这应该是正确的答案,我想说的是 maniac_ 答案的第二部分指出:“但是..会失败”他的意思是它会在 BASH 上的 CMD 中失败但不会失败如果是 crontab 如果您在非英语语言环境中,这将失败(因为%a
输出特定于语言环境的字符串)。它也不能移植到其他 Unix,其中 /bin/sh
是一个带有 [
实现的 shell,不支持 ==
运算符(例如 Ubuntu,其中 /bin/sh
是 Dash)。【参考方案6】:
在第 1 个星期一、第 3 个星期二、上个星期日等任何时间运行一个 cron 任务。
http://xr09.github.io/cron-last-sunday/
只需将run-if-today
脚本放在路径中并与cron 一起使用即可。
30 6 * * 6 root run-if-today 1 Sat && /root/myfirstsaturdaybackup.sh
如果日期正确,run-if-today
脚本只会返回 0(True 的 bash 值)。
编辑:
现在界面更简单,周数只有一个参数。
# run every first saturday
30 6 * * 6 root run-if-today 1 && /root/myfirstsaturdaybackup.sh
# run every last sunday
30 6 * * 7 root run-if-today L && /root/lastsunday.sh
【讨论】:
在第一种格式中,脚本是独立的。在更简单的格式中,脚本取决于星期几参数。我说对了吗? 正是@Ashfaq,因为您已经在 cron 上说明了工作日,因此无需在脚本上检查它,它限制自己检查它是第 1 周、第 2 周、第 3 周或第 4 周。现在,如果您想在没有 cron 的情况下使用它,那么使用第一种格式并检查工作日是有意义的。【参考方案7】:也许使用 cron.hourly 来调用另一个脚本。然后该脚本将检查它是否是该月的第一个星期日和上午 9 点,如果是,则运行您的程序。听起来对我来说足够理想:-)。
【讨论】:
除非您还不如每天调用它:这是一个鲜为人知的事实,即一天改变一次。 ;) 感谢您的回答 虽然没什么大不了的,但为什么要每小时运行一个脚本?我宁愿寻找每周日运行的每周脚本。但想知道是否有人已经做过类似的事情。 我对 cron 没有经验,这就是为什么,可能有更好的方法。但是每小时轮询一次你的条件脚本会让你接近上午 9 点。 Daily 并没有真正告诉你它什么时候会在白天运行,而你指定了上午 9 点。【参考方案8】:如果您不希望 cron 每天或每周日运行您的作业,您可以编写一个包装器来运行您的代码,确定下一个第一个星期日,并安排自己在该日期运行。
然后将该包装器安排在该月的下一个第一个星期日。之后它会自己处理所有事情。
代码将类似于(强调某事...没有进行错误检查):
#! /bin/bash
#We run your code first
/path/to/your/code
#now we find the next day we want to run
nskip=28 #the number of days we want to check into the future
curr_month=`date +"%m"`
new_month=`date --date='$nskip days' +"%m"`
if [[ curr_month = new_month ]]
then
((nskip+=7))
fi
date=`date --date='$nskip days' +"09:00AM %D` #you may need to change the format if you use another scheduler
#schedule the job using "at"
at -m $date < /path/to/wrapper/code
查找下一个第一个星期日的逻辑很简单。由于我们从本月的第一个星期日开始,加上 28 将使我们处于本月的最后一个星期日或下个月的第一个星期日。如果是当月,则递增到下周日(即下个月的第一周)。
我用了“at”。我不知道这算不算作弊。主要想法是找到下一个第一个星期日。之后您可以替换任何您想要的调度程序,因为您知道要运行作业的日期和时间(不过,不同的调度程序可能需要不同的日期语法)。
【讨论】:
这比使用 Cron 复杂得多,我认为它没有任何优势; -1.【参考方案9】:试试下面的
0 15 10 ? * 1#1
http://www.quartz-scheduler.org/documentation/quartz-1.x/tutorials/crontrigger
【讨论】:
-1;这不起作用,因为?
语法不是常规 Unix Cron 的一部分。它是 Quartz Scheduler 中语法的扩展。
搞笑的是,这正是我想要的,尽管它绝对不是原始问题的答案。如果您使用 Rundeck,这就是您想要的。【参考方案10】:
00 09 1-7 * 0 /usr/local/bin/once_a_week
每月前 7 天的每个星期日
【讨论】:
抱歉,这个实际上会在每个星期天和每月的前 7 天工作。见这里:***.com/a/6203414/327064以上是关于如何安排每个月的第一个星期日运行的主要内容,如果未能解决你的问题,请参考以下文章