如何安排每个月的第一个星期日运行

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

以上是关于如何安排每个月的第一个星期日运行的主要内容,如果未能解决你的问题,请参考以下文章

如何找到每个月的第三周?第 1 周从每月的第一个星期一开始

有啥东西可以代表像“每个月的第一个星期一”这样的时期吗?

在詹金斯上安排两周一次的工作

获取日历月的第一个星期一

js如何判断 每年每个月的第一天是星期几?

如何获取每个月的第二个星期五的日期范围?