克朗工作在本月的最后一天运行
我需要创build一个将在每个月的最后一天运行的cron作业。 我将从cPanel创build它。
任何帮助表示赞赏。 谢谢
可能最简单的方法是简单地做三个单独的工作:
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
即使在闰年,即使在2月28日,如果这是一个问题,你将需要另辟蹊径。
然而,在每个月的第一天尽快完成这项工作通常都是非常简单和正确的,例如:
0 0 1 * * myjob.sh
并修改脚本以处理上个月的数据。
这可以消除您在确定哪一天是最后一个月的过程中可能遇到的任何麻烦,还可以确保当月的所有数据都可用,假设您正在处理数据。 在本月的最后一天的五点钟到午夜时分,您可能会看到您错过了午夜至午夜之间发生的任何事情。
无论如何,这是通常的做法,对于大部分月末工作。
如果你仍然真的想在每个月的最后一天运行它,一个select是简单地检测明天是否是第一个(作为脚本的一部分,或者在crontab本身)。
所以,像这样的:
55 23 28-31 * * [[ "$(date --date=tomorrow +\%d)" == "01" ]] && myjob.sh
应该是一个好的开始,假设你有一个相对智能的date
程序。
如果你的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; }
然后使用(假设你把它称为“明天”):
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
设置一个cron作业在本月的第一天运行。 然后改变系统的时钟提前一天。
那么维基百科之后呢?
55 23 L * * /full/path/to/command
调整paxdiablo的解决scheme,我在二月二十八日和二十九日运行。 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
您可以设置一个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
00 23 * * * [[ $(date +'%d') -eq $(cal | awk '!/^$/{ print $NF }' | tail -1) ]] && job
查看unix.com论坛上的相关问题 。
某些 cron实现支持“L”标志来表示本月的最后一天。
如果您很幸运能够使用这些实现中的一种,那么就像下面这样简单:
0 55 23 L * ?
这将在每个月的最后一天下午11:55运行。
http://www.quartz-scheduler.org/documentation/quartz-1.x/tutorials/crontrigger
对于基于@Indie解决scheme的crontab中更安全的方法(使用绝对path到date
+ $()
不适用于所有crontab系统):
0 23 28-31 * * [ `/bin/date -d +1day +\%d` -eq 1 ] && myscript.sh
你可以在一个cron行中连接所有的答案,只使用date
命令。
只要检查今天和明天的月份之间的差异:
0 23 * * * root [ $(expr $(date +\%d -d '1 days') - $(date +\%d) ) -le 0 ] && echo true
如果这些差值低于0,则意味着我们改变月份,并且有月份的最后一天。
######################################################### # 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 #VVVVVV * * 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"
那这个呢?
编辑用户的.bashprofile
添加:
export LAST_DAY_OF_MONTH=$(cal | awk '!/^$/{ print $NF }' | tail -1)
然后将这个条目添加到crontab中:
mm hh * * 1-7 [[ $(date +'%d') -eq $LAST_DAY_OF_MONTH ]] && /absolutepath/myscript.sh