我需要创建一个CRON作业,该作业将在每个月的最后一天运行。我将使用cPanel创建它。
任何帮助表示赞赏。谢谢
我需要创建一个CRON作业,该作业将在每个月的最后一天运行。我将使用cPanel创建它。
任何帮助表示赞赏。谢谢
Answers:
可能最简单的方法是简单地做三个单独的工作:
55 23 30 4,6,9,11 * myjob.sh
55 23 31 1,3,5,7,8,10,12 * myjob.sh
55 23 28 2 * myjob.sh
不过,即使是leap年,也要在2月28日进行,如果这是一个问题,则需要寻找其他方法。
但是,通常在每个月的第一天尽快进行这项工作既容易又正确,实际上是这样的:
0 0 1 * * myjob.sh
并修改脚本来处理以前一个月的数据。
这将消除您在确定哪一天是每月的最后一天时可能会遇到的麻烦,并确保假设您正在处理数据,该月的所有数据都可用。在当月最后一天的午夜五点钟跑步,您可能会错过从那时到午夜之间发生的任何事情。
无论如何,对于大多数月底工作,这都是通常的方法。
如果您仍然真的想在一个月的最后一天运行它,一个选择是简单地检测明天是否是第一个(作为脚本的一部分,或者在crontab本身中)。
因此,类似:
55 23 28-31 * * [[ "$(date --date=tomorrow +\%d)" == "01" ]] && myjob.sh
假设您有一个相对智能的date
程序,应该是一个好的开始。
如果您的date
程序不够先进,无法为您提供相对日期,则可以将一个非常简单的程序组合在一起,即可为您提供明天的明天(您不需要的全部功能date
),例如:
#include <stdio.h>
#include <time.h>
int main (void) {
// Get today, somewhere around midday (no DST issues).
time_t noonish = time (0);
struct tm *localtm = localtime (&noonish);
localtm->tm_hour = 12;
// Add one day (86,400 seconds).
noonish = mktime (localtm) + 86400;
localtm = localtime (&noonish);
// Output just day of month.
printf ("%d\n", localtm->tm_mday);
return 0;
}
然后使用(假设您将其称为tomdom
“明天的月份”):
55 23 28-31 * * [[ "$(tomdom)" == "1" ]] && myjob.sh
虽然您可能要考虑添加错误检查,因为两者都可以,time()
并且如果出现问题mktime()
可以返回-1
。为了简单起见,上面的代码没有考虑到这一点。
与上述方法之一类似,可以使用一种稍短的方法。那是:
[ $(date -d +1day +%d) -eq 1 ] && echo "last day of month"
另外,crontab条目可能会更新为仅在28号到31号进行检查,因为它在每月的其他几天都没有意义。这会给你:
0 23 28-31 * * [ $(date -d +1day +%d) -eq 1 ] && myscript.sh
/bin/sh: -c: line 1: unexpected EOF while looking for matching ')'
。
[ $(date -d +1day +\%d) -eq 1 ] && run_job
posix
,POSIX日期不支持"-d +1day"
:-\一个更复杂(又丑陋)的解决方案是:[ `date +\%d` -eq `cal | xargs echo | awk '{print $NF}'` ] && myscript.sh
设置Cron作业以在每月的第一天运行。然后将系统时钟更改为提前一天。
那在维基百科之后呢?
55 23 L * * /full/path/to/command
根据paxdiablo的解决方案,我于2月28 日至 29日跑步。来自29号的数据将覆盖28号。
# min hr date month dow
55 23 31 1,3,5,7,8,10,12 * /path/monthly_copy_data.sh
55 23 30 4,6,9,11 * /path/monthly_copy_data.sh
55 23 28,29 2 * /path/monthly_copy_data.sh
,29
。
55 23 28 2
吗?
您可以设置一个cron作业在每月的每一天运行,并使其运行如下所示的shell脚本。该脚本计算出明天的天数是否小于今天的天数(即,如果明天是一个新月),然后执行您想要的任何事情。
TODAY=`date +%d`
TOMORROW=`date +%d -d "1 day"`
# See if tomorrow's day is less than today's
if [ $TOMORROW -lt $TODAY ]; then
echo "This is the last day of the month"
# Do stuff...
fi
一些 cron实现支持“ L”标志来表示月份的最后一天。
如果您很幸运地使用了其中一种实现,则非常简单:
0 55 23 L * ?
该活动将在每个月的最后一天晚上11:55进行。
http://www.quartz-scheduler.org/documentation/quartz-1.x/tutorials/crontrigger
#########################################################
# Memory Aid
# environment HOME=$HOME SHELL=$SHELL LOGNAME=$LOGNAME PATH=$PATH
#########################################################
#
# string meaning
# ------ -------
# @reboot Run once, at startup.
# @yearly Run once a year, "0 0 1 1 *".
# @annually (same as @yearly)
# @monthly Run once a month, "0 0 1 * *".
# @weekly Run once a week, "0 0 * * 0".
# @daily Run once a day, "0 0 * * *".
# @midnight (same as @daily)
# @hourly Run once an hour, "0 * * * *".
#mm hh Mday Mon Dow CMD # minute, hour, month-day month DayofW CMD
#........................................Minute of the hour
#| .................................Hour in the day (0..23)
#| | .........................Day of month, 1..31 (mon,tue,wed)
#| | | .................Month (1.12) Jan, Feb.. Dec
#| | | | ........day of the week 0-6 7==0
#| | | | | |command to be executed
#V V V V V V
* * 28-31 * * [ `date -d +'1 day' +\%d` -eq 1 ] && echo "Tomorrow is the first today now is `date`" >> ~/message
1 0 1 * * rm -f ~/message
* * 28-31 * * [ `date -d +'1 day' +\%d` -eq 1 ] && echo "HOME=$HOME LOGNAME=$LOGNAME SHELL = $SHELL PATH=$PATH"
您只需将所有答案连接在一个cron行中,并仅使用date
命令即可。
只需检查今天和明天之间的月份之间的差额即可:
0 23 * * * root [ $(expr $(date +\%d -d '1 days') - $(date +\%d) ) -le 0 ] && echo true
如果这些差值小于0,则表示我们更改了月份,并且该月的最后一天。
一个月的最后一天可以是28-31,具体取决于哪个月(2月,3月等)。但是,在这两种情况下,第二天始终是下个月的1号。因此我们可以使用以下代码来确保始终在一个月的最后一天运行某些作业:
0 8 28-31 * * [ "$(date +%d -d tomorrow)" = "01" ] && /your/script.sh