Cron工作在本月的最后一天运行

时间:2011-05-26 13:22:56

标签: automation cron posix

我需要创建一个将在每个月的最后一天运行的cron作业。 我将从cpanel创建它。

感谢任何帮助。 感谢

15 个答案:

答案 0 :(得分:148)

最简单的方法可能就是完成三个单独的工作:

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

并修改脚本以处理上一个月的数据。

这可以消除您在确定哪一天是该月的最后一天时遇到的任何麻烦,并且还可以确保该月的所有数据都可用,假设您正在处理数据。在每个月的最后一天五分钟到午夜运行可能会发现你错过了当时和午夜之间发生的任何事情。

无论如何,对于大多数月末工作来说,这是通常的方法。


如果你仍然 希望在一个月的最后一天运行它,一个选项是简单地检测明天是否是第一个(作为脚本的一部分,或者在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。出于简单的原因,上面的代码没有考虑到这一点。

答案 1 :(得分:45)

可以使用类似于上述方法之一的稍短的方法。那就是:

[ $(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

答案 2 :(得分:18)

设置一个cron作业,在该月的第一天运行。然后将系统的时钟更改为提前一天。

答案 3 :(得分:10)

在维基百科之后呢?

55 23 L * * /full/path/to/command

答案 4 :(得分:10)

改编paxdiablo的解决方案,我在2月29日 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

答案 5 :(得分:6)

您可以设置一个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

答案 6 :(得分:5)

某些 cron实现支持“L”标志来表示该月的最后一天。

如果您很幸运能够使用其中一种实现,那就很简单:

0 55 23 L * ?

这将在每个月的最后一天晚上11:55运行。

http://www.quartz-scheduler.org/documentation/quartz-1.x/tutorials/crontrigger

答案 7 :(得分:4)

00 23 * * * [[ $(date +'%d') -eq $(cal | awk '!/^$/{ print $NF }' | tail -1) ]] && job

在unix.com论坛上查看related question

答案 8 :(得分:4)

对于基于@Indie解决方案的crontab中更安全的方法(使用date + $()的绝对路径不适用于所有crontab系统):

0 23 28-31 * * [ `/bin/date -d +1day +\%d` -eq 1 ] && myscript.sh

答案 9 :(得分:4)

#########################################################
# 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" 

答案 10 :(得分:4)

对于AWS Cloudwatch cron实现(Scheduling Lambdas等),这有效:

MATCH (p:Product {type:'TV'})
WHERE (p)-[:HAS_ATTRIBUTES|HAS_EXTRA_ATTRIBUTES]->({color:'red'})
...

在每个月的最后一天晚上11:55运行。

答案 11 :(得分:3)

您只需在一个cron行中连接所有答案,并仅使用date命令。

只需检查今天和明天之间的日期差异:

0 23 * * * root [ $(expr $(date +\%d -d '1 days') - $(date +\%d)  ) -le 0 ]  && echo true

如果这些差异低于0,则表示我们更改月份,并且该月份的最后一天。

答案 12 :(得分:2)

这个怎么样?

修改用户.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

答案 13 :(得分:1)

一个月的最后一天可以是28-31,具体取决于哪个月(2月,3月等)。但是,在这两种情况下,第二天始终是下个月的1号。因此,我们可以使用以下代码来确保始终在一个月的最后一天运行某些作业:

0 8 28-31 * * [ "$(date +%d -d tomorrow)" = "01" ] && /your/script.sh

答案 14 :(得分:0)

不确定其他语言,但在javascript中是可能的。

如果您需要在一个月的第一天之前完成您的工作 node-cron 将允许您设置时区 - 您必须设置 UTC+12:00 并且如果工作不是太长世界上所有的人都会在本月开始前出结果。