English 中文(简体)
CRON作业将在本月最后一天运行
原标题:CRON job to run on the last day of the month

I need to create a CRON job that will run on the last day of every month. I will create it using cPanel.

Any help is appreciated. Thanks

最佳回答

可能最简单的方法是简单地做三项单独的工作:

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程序,这应该是一个良好的开端。

如果您的日期程序不够高级,无法为您提供相对日期,您可以编写一个非常简单的程序,为您提供明天的日期(您不需要完整功能),例如:

#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
", localtm->tm_mday);

    return 0;
}

然后使用(假设您将其称为tomdom表示“明天的一个月”):

55 23 28-31 * * [[ "$(tomdom)" == "1" ]] && myjob.sh

尽管您可能需要考虑添加错误检查,因为如果出现问题,time()mktime()[/code>都可以返回-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

对于AWS Cloudwatch cron实现(Scheduling Lambdas等),这是可行的:

55 23 L * ? *

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

维基百科之后的这个呢?

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

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

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

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

如果你很幸运地使用了其中一个实现,它很简单:

0 55 23 L * ?

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

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

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

我在此站点

 0 0 0 L * ? *

CRON细节:

Seconds Minutes Hours   Day Of Month    Month   Day Of Week  Year
0       0       0       L               *       ?            *

若要交叉验证上述表达式,单击此处,它会给出如下输出。

2021-12-31 Fri 00:00:00
2022-01-31 Mon 00:00:00
2022-02-28 Mon 00:00:00
2022-03-31 Thu 00:00:00
2022-04-30 Sat 00:00:00

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

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

查看unix.com论坛上的相关问题

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

只需检查一个月中今天和明天之间的差异:

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

如果这些差值小于0,则意味着我们更改了月份,并且存在该月的最后一天。

55 23 28-31 * * echo "[ $(date -d +1day +%d) -eq 1 ] && my.sh" | /bin/bash 

在像Jenkins这样的工具中,通常不支持L,也不支持类似于date的工具,一个很酷的技巧可能是正确设置时区。例如,太平洋/基里蒂马蒂是GMT+14:00,所以如果你在欧洲或美国,这可能会奏效。

TZ=Pacific/Kiritimati 
 H 0 1 * * 

结果:将于2022年4月30日星期六上午10:54:53 GMT进行最后一次跑步;下一次将于2022年5月31日星期二上午10:54:53 GMT运行。

这个怎么样?

编辑用户的.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

使用以下代码在一个月的最后一天用PHP运行cron

$commands =  30 23  .date( t ).   .date( n ).  * ;

一个月的最后一天可以是28-31,这取决于它是哪个月(二月、三月等)。然而,在这两种情况下,第二天总是下个月的第一天。因此,我们可以使用以下代码来确保我们总是在一个月的最后一天运行一些作业:

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

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

如果您需要在每月的第一天之前完成作业,节点cron将允许您设置时区-您必须设置UTC+12:00,如果作业不太长,世界上大多数地区都会在月初之前得到结果。

如果“月日”字段可以接受“零日”,这将非常简单地解决这个问题。天文学家用零点来表示上个月的最后一天。所以

00 08 00 * * /usr/local/sbin/backup

会以简单易行的方式完成这项工作。

将cron安排在下个月的第1天的更好方法

这将在12:00AM运行命令foo。

0 0 1**/usr/bin/foo

如果在午夜到凌晨1点之间运行,请谨慎使用日期程序中的“昨天”、“今天”和“1天”,因为这些通常意味着“24小时”,即夏令时变化导致一天23小时的两天。我使用“日期-d凌晨1点-12小时”





相关问题
Deploying WCF application

I have IIS-Hosted WCF application and services. I want to automate the process to deploy this application into test/Acceptance test/production environments What is the best way to automate the process ...

CGWindowID from AXUIElement

I m trying to automate a foreign OSX application using the accessibility API. Some of the state of the application isn t available through the API, so I acquire it through screen scraping. To do this, ...

Snapping pictures from Windows C# Canon SDK vs PTP or MTP

I am hoping to receive some general guidance on accomplishing a seemingly simple goal. I have a DSLR camera (Canon EOS 50D) and need to write an application that will tell the camera to take a ...