bash 如何安排每个月的第一个星期日运行
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3241086/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to schedule to run first Sunday of every month
提问by ring bearer
I am using Bash on RedHat. I need to schedule a cron job to run at at 9:00 AM on first Sunday of every month. How can I do this?
我在 RedHat 上使用 Bash。我需要安排一个 cron 作业在每个月的第一个星期日上午 9:00 运行。我怎样才能做到这一点?
回答by Lukasz Stelmach
You can put something like this in the crontab
file:
你可以把这样的东西放在crontab
文件中:
00 09 * * 7 [ $(date +\%d) -le 07 ] && /run/your/script
The date +%d
gives you the number of the current day, and then you can check if the day is less than or equal to 7. If it is, run your command.
该date +%d
给你当天的号码,然后你可以检查当天小于或等于7。如果是这样,运行命令。
If you run this script only on Sundays, it should mean that it runs only on the first Sunday of the month.
如果您仅在星期日运行此脚本,则应该意味着它仅在该月的第一个星期日运行。
Remember that in the crontab
file, the formatting options for the date
command should be escaped.
请记住,在crontab
文件中,date
应该对命令的格式选项进行转义。
回答by Mark Amery
It's worth noting that what looks like the most obvious approach to this problem does notwork.
值得一提的是,是什么样子的最显而易见的方法解决这个问题确实不工作。
You might think that you could just write a crontab entry that specifies the day-of-week as 0 (for Sunday) and the day-of-month as 1-7, like this...
您可能认为您可以编写一个 crontab 条目,将星期几指定为 0(星期日),将月份指定为 1-7,就像这样...
# This does NOT work.
0 9 1-7 * 0 /path/to/your/script
... but, due to an eccentricity of how Cron handles crontab lines with both a day-of-week and day-of-month specified, this won't work, and will in fact run on the 1st, 2nd, 3rd, 4th, 5th, 6th, and 7th of the month (regardless of what day of the week they are) andon everySunday of the month.
...但是,由于Cron 处理 crontab 行的方式与指定的星期几和日期不同,这将不起作用,实际上将在 1 日、2 日、3 日运行, 4日,5日,6日和本月7日(不管它们是什么星期几),并在每一个月的星期天。
This is why you see the recommendation of using a [ ... ]
check with date
to set up a rule like this - either specifying the day-of-week in the crontab and using [
and date
to check that the day-of-month is <=7 before running the script, as shown in the accepted answer, or specifying the day-of-month range in the crontab and using [
and date
to check the day-of-week before running, like this:
这就是为什么你看到使用的建议[ ... ]
检查与date
建立这样的规则-无论是指定目前的crontab中某一天的一周,使用[
和date
检查,当天的日是<= 7上运行的前脚本,如已接受的答案所示,或在 crontab 中指定日期范围并在运行前使用[
和date
检查星期几,如下所示:
# This DOES work.
0 9 1-7 * * [ $(date +\%u) = 7 ] && /path/to/your/script
Some best practices to keep in mind if you'd like to ensure that your crontab line will work regardlessof what OS you're using it on:
如果您想确保您的 crontab 行无论您在什么操作系统上使用它都能正常工作,请记住一些最佳实践:
- Use
=
, not==
, for the comparison. It's more portable, since not all shells use an implementation of[
that supports the==
operator. - Use the
%u
specifier todate
to get the day-of-week as a number, not the%a
operator, because%a
gives different results depending upon the localedate
is being run in. - Just use
date
, not/bin/date
or/usr/bin/date
, since thedate
utility has different locations on different systems.
- 使用
=
,而不是==
进行比较。它更易于移植,因为并非所有 shell 都使用[
支持==
运算符的实现。 - 使用说明
%u
符 todate
将星期几作为数字而不是%a
运算符获取,因为%a
根据date
运行的语言环境给出不同的结果。 - 只需使用
date
、 不/bin/date
或/usr/bin/date
,因为该date
实用程序在不同系统上的位置不同。
回答by Dirk Eddelbuettel
You need to combine two approaches:
您需要结合两种方法:
a) Use cron
to run a job every Sunday at 9:00am.
a) 用于cron
每周日上午 9:00 运行作业。
00 09 * * 7 /usr/local/bin/once_a_week
b) At the beginning of once_a_week
, compute the date and extract the day of the month via shell, Python, C/C++, ... and test that is within 1 to 7, inclusive. If so, execute the real script; if not, exit silently.
b) 在 的开头once_a_week
,通过 shell、Python、C/C++ 等计算日期并提取月份中的第几天,并在 1 到 7 之间进行测试,包括 1 到 7。如果是,执行真正的脚本;如果没有,请静默退出。
回答by thesunneversets
A hacky solution: have your cron job run every Sunday, but have your script check the date as it starts, and exit immediately if the day of the month is > 7...
一个hacky解决方案:让你的cron作业每周日运行,但让你的脚本在开始时检查日期,如果当月的日期> 7,则立即退出......
回答by MGP
Run a cron task 1st monday, 3rd tuesday, last sunday, anything..
在第 1 个星期一、第 3 个星期二、上个星期天,任何时间运行 cron 任务。
http://xr09.github.io/cron-last-sunday/
http://xr09.github.io/cron-last-sunday/
Just put the run-if-today
script in the path and use it with cron.
只需将run-if-today
脚本放在路径中并与 cron 一起使用即可。
30 6 * * 6 root run-if-today 1 Sat && /root/myfirstsaturdaybackup.sh
The run-if-today
script will only return 0 (bash value for True) if it's the right date.
run-if-today
如果它是正确的日期,脚本将只返回 0(真的 bash 值)。
EDIT:
编辑:
Now with simpler interface, just one parameter for week number.
现在有了更简单的界面,周数只有一个参数。
# 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
回答by maniac_on_moon
This also works with names of the weekdays:
这也适用于工作日的名称:
0 0 1-7 * * [ "$(date '+\%a')" == "Sun" ] && /usr/local/bin/urscript.sh
But,
但,
[ "$(date '+\%a')" == "Sun" ] && echo SUNDAY
[ "$(date '+\%a')" == "Sun" ] && echo SUNDAY
will FAILon comandline due to special treatment of "%" in crontab (also valid for https://stackoverflow.com/a/3242169/2919695)
由于 crontab 中对“%”的特殊处理,命令行将失败(也适用于https://stackoverflow.com/a/3242169/2919695)
回答by user390948
If you don't want cron to run your job everyday or every Sunday you could write a wrapper that will run your code, determine the next first Sunday, and schedule itself to run on that date.
如果您不希望 cron 每天或每个星期天都运行您的工作,您可以编写一个包装器来运行您的代码,确定下一个第一个星期日,并安排自己在该日期运行。
Then schedule that wrapper for the next first Sunday of the month. After that it will handle everything itself.
然后将该包装器安排在该月的下一个第一个星期日。之后它会自己处理一切。
The code would be something like (emphasis on something...no error checking done):
代码将类似于(强调某事...没有进行错误检查):
#! /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
The logic is simple to find the next first Sunday. Since we start on the first Sunday of the current month, adding 28 will either put us on the last Sunday of the current month or the first Sunday of the next month. If it is the current month, we increment to the next Sunday (which will be in the first week of the next month).
查找下一个第一个星期日的逻辑很简单。由于我们从当月的第一个星期日开始,加上 28 将使我们处于当月的最后一个星期日或下个月的第一个星期日。如果是当月,我们递增到下一个星期日(将在下个月的第一周)。
And I used "at". I don't know if that is cheating. The main idea though is finding the next first Sunday. You can substitute whatever scheduler you want after that, since you know the date and time you want to run the job (a different scheduler may need a different syntax for the date, though).
我用了“在”。不知道是不是骗人 主要的想法是找到下一个星期日。之后您可以替换任何您想要的调度程序,因为您知道要运行作业的日期和时间(不过,不同的调度程序可能需要不同的日期语法)。
回答by gtrak
maybe use cron.hourly to call another script. That script will then check to see if it's the first sunday of the month and 9am, and if so, run your program. Sounds optimal enough to me :-).
也许使用 cron.hourly 来调用另一个脚本。然后该脚本将检查是否是该月的第一个星期日和上午 9 点,如果是,则运行您的程序。对我来说听起来足够理想:-)。
回答by Anup
try the following
尝试以下
0 15 10 ? * 1#1
0 15 10 ? * 1#1
http://www.quartz-scheduler.org/documentation/quartz-1.x/tutorials/crontrigger
http://www.quartz-scheduler.org/documentation/quartz-1.x/tutorials/crontrigger
回答by Nicola Iannello
00 09 1-7 * 0 /usr/local/bin/once_a_week
00 09 1-7 * 0 /usr/local/bin/once_a_week
every sunday of first 7 days of the month
每月前 7 天的每个星期日