如何安排每个月的第一个星期天

时间:2010-07-13 20:12:12

标签: bash shell cron redhat

我在RedHat上使用Bash。我需要安排一个cron工作在每个月的第一个星期日上午9点运行。我怎么能这样做?

10 个答案:

答案 0 :(得分:128)

您可以在crontab文件中输入类似内容:

00 09 * * 7 [ $(date +\%d) -le 07 ] && /run/your/script

date +%d为您提供当天的号码,然后您可以检查当天是否小于或等于7.如果是,请运行您的命令。

如果您仅在星期日运行此脚本,则应表示它仅在该月的第一个星期日运行。

请记住,在crontab文件中,应转义date命令的格式设置选项。

答案 1 :(得分:12)

您需要结合两种方法:

a)使用cron每周日上午9:00开始工作。

 00 09 * * 7     /usr/local/bin/once_a_week

b)在once_a_week的开头,计算日期并通过shell,Python,C / C ++,...和1到7之间的测试来提取月份的日期。如果是这样,执行真实的脚本;如果没有,请默默退出。

答案 2 :(得分:5)

一个hacky解决方案:让你的cron作业每个星期天运行,但让你的脚本在开始时检查日期,如果当月的日期是> 1,则立即退出。 7 ...

答案 3 :(得分:5)

第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(bash值为True),如果它是正确的日期。

编辑:

现在界面更简单,只有一个参数用于周数。

# 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

答案 4 :(得分:5)

值得注意的是,看起来最明显的解决此问题的方法无效有效。

您可能会认为您可以编写一个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中指定星期几并使用{{3} }和[,以便在运行脚本之前检查月份的天数是否小于等于7,如date所示,或者在crontab中指定月份的天数范围并使用{ {1}}和[检查运行前的星期几,例如:

date

如果要确保您的crontab行不管您在哪个操作系统上使用,都应牢记一些最佳做法:

  • 使用# This DOES work. 0 9 1-7 * * [ $(date +\%u) = 7 ] && /path/to/your/script 而非=进行比较。由于不是所有的shell都使用支持==运算符的[实现,所以它更加可移植。
  • 使用==%u的说明符来获取星期几,而不是date运算符,因为%a根据区域设置%a正在运行。
  • 只需使用date,而不要使用date/bin/date,因为/usr/bin/date实用程序在不同系统上的位置不同。

答案 5 :(得分:4)

这也适用于工作日的名称:

0 0 1-7 * * [ "$(date '+\%a')" == "Sun" ] && /usr/local/bin/urscript.sh

但是,

[ "$(date '+\%a')" == "Sun" ] && echo SUNDAY

由于crontab中对“%”的特殊处理(也适用于https://stackoverflow.com/a/3242169/2919695),

将在comandline上 FAIL

答案 6 :(得分:0)

也许使用cron.hourly来调用另一个脚本。然后该脚本将检查它是否是本月的第一个星期日和上午9点,如果是,则运行您的程序。听起来对我来说最合适: - )。

答案 7 :(得分:0)

如果您不希望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”。我不知道这是不是在作弊。但主要的想法是找到下一个第一个星期天。您可以替换之后想要的任何调度程序,因为您知道要运行作业的日期和时间(不同的调度程序可能需要不同的日期语法)。

答案 8 :(得分:-1)

答案 9 :(得分:-3)

00 09 1-7 * 0 / usr / local / bin / once_a_week

每月前7天的每个星期日