在这个月的最后一天上班

时间:2022-10-16 12:29:36

I need to create a cron job that will run on the every last day of the month. I will create it from cpanel.

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

Any help is appreciated. Thanks

任何帮助都是感激。谢谢

13 个解决方案

#1


121  

Possibly the easiest way is to simply do three separate jobs:

可能最简单的方法就是做三个不同的工作:

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

That will run on the 28th of February though, even on leap years so, if that's a problem, you'll need to find another way.

这将在2月28日,即使是闰年,所以,如果这是一个问题,你需要找到另一种方法。


However, it's usually both substantially easier and correct to run the job as soon as possible on the first day of each month, with something like:

然而,通常在每个月的第一天就尽可能快地完成工作是非常容易和正确的,比如:

0 0 1 * * myjob.sh

and modify the script to process the previous month's data.

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

This removes any hassles you may encounter with figuring out which day is the last of the month, and also ensures that all data for that month is available, assuming you're processing data. Running at five minutes to midnight on the last day of the month may see you missing anything that happens between then and midnight.

这将消除您可能遇到的任何麻烦,以确定哪一天是一个月的最后一天,并确保该月份的所有数据都是可用的,假设您正在处理数据。在一个月的最后一天,在午夜前五分钟跑步,你可能会错过从午夜到午夜之间发生的一切。

This is the usual way to do it anyway, for most end-of-month jobs.

不管怎样,对于大多数月末的工作来说,这是通常的做法。


If you still really want to run it on the last day of the month, one option is to simply detect if tomorrow is the first (either as part of your script, or in the crontab itself).

如果您仍然想在这个月的最后一天运行它,一个选项是简单地检测明天是否是第一天(作为脚本的一部分,或者作为crontab本身)。

So, something like:

所以,类似:

55 23 28-31 * * [[ "$(date --date=tomorrow +\%d)" == "01" ]] && myjob.sh

should be a good start, assuming you have a relatively intelligent date program.

如果你有一个相对智能的约会程序,这应该是一个好的开始。

If your date program isn't quite advanced enough to give you relative dates, you can just put together a very simple program to give you tomorrow's day of the month (you don't need the full power of date), such as:

如果你的约会程序不够先进,不能给你提供相对的约会日期,你可以制作一个非常简单的程序,给你一个月的明天(你不需要日期的全部力量),例如:

#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;
}

and then use (assuming you've called it tomdom for "tomorrow's day of month"):

然后使用(假设你把它叫做tomdom,表示“每月的明天”):

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

Though you may want to consider adding error checking since both time() and mktime() can return -1 if something goes wrong. The code above, for reasons of simplicity, does not take that into account.

尽管您可能需要考虑添加错误检查,因为如果出现问题,time()和mktime()都可以返回-1。由于简单性的原因,上面的代码没有考虑到这一点。

#2


39  

There's a slightly shorter method that can be used similar to one of the ones above. That is:

有一种稍微短一点的方法可以使用,类似于上面的方法。那就是:

[ $(date -d +1day +%d) -eq 1 ] && echo "last day of month"

Also, the crontab entry could be update to only check on the 28th to 31st as it's pointless running it the other days of the month. Which would give you:

此外,crontab条目可以更新为只检查28 - 31号,因为在这个月的其他日子运行它是没有意义的。这将给你:

0 23 28-31 * * [ $(date -d +1day +%d) -eq 1 ] && myscript.sh

#3


18  

Set up a cron job to run on the first day of the month. Then change the system's clock to be one day ahead.

在一个月的第一天设立一个cron作业。然后改变系统的时钟,让它提前一天。

#4


9  

What about this one, after Wikipedia?

*之后的这个呢?

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

#5


8  

Adapting paxdiablo's solution, I run on the 28th and 29th of February. The data from the 29th overwrites the 28th.

改编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

#6


5  

You could set up a cron job to run on every day of the month, and have it run a shell script like the following. This script works out whether tomorrow's day number is less than today's (i.e. if tomorrow is a new month), and then does whatever you want.

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

#7


4  

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

Check out a related question on the unix.com forum.

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

#8


4  

Some cron implementations support the "L" flag to represent the last day of the month.

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

If you're lucky to be using one of those implementations, it's as simple as:

如果您幸运地使用了其中的一种实现,那么简单如下:

0 55 23 L * ?

That will run at 11:55 pm on the last day of every month.

每个月的最后一天晚上11点55分。

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

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

#9


3  

For a safer method in a crontab based on @Indie solution (use absolute path to date + $() does not works on all crontab systems):

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

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

#10


3  

You can just connect all answers in one cron line and use only date command.

您可以将所有答案连接到一个cron行中,并且只使用date命令。

Just check the difference between day of the month which is today and will be tomorrow:

检查一下这个月的一天和明天的区别:

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

If these difference is below 0 it means that we change the month and there is last day of the month.

如果这些差值小于0,这意味着我们要改变月份,这是一个月的最后一天。

#11


3  

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

#12


1  

What about this?

这是什么?

edit user's .bashprofile adding:

编辑用户的.bashprofile添加:

export LAST_DAY_OF_MONTH=$(cal | awk '!/^$/{ print $NF }' | tail -1)

Then add this entry to crontab:

然后把这个条目添加到crontab:

mm hh * * 1-7 [[ $(date +'%d') -eq $LAST_DAY_OF_MONTH ]] && /absolutepath/myscript.sh

#13


-1  

For AWS Cloudwatch cron implementation (Scheduling Lambdas, etc..) this works:

对于AWS Cloudwatch cron实现(调度Lambdas等),这是有效的:

55 23 L * ? *

Running at 11:55pm on the last day of each month.

在每个月的最后一天晚上11点55分跑步。

#1


121  

Possibly the easiest way is to simply do three separate jobs:

可能最简单的方法就是做三个不同的工作:

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

That will run on the 28th of February though, even on leap years so, if that's a problem, you'll need to find another way.

这将在2月28日,即使是闰年,所以,如果这是一个问题,你需要找到另一种方法。


However, it's usually both substantially easier and correct to run the job as soon as possible on the first day of each month, with something like:

然而,通常在每个月的第一天就尽可能快地完成工作是非常容易和正确的,比如:

0 0 1 * * myjob.sh

and modify the script to process the previous month's data.

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

This removes any hassles you may encounter with figuring out which day is the last of the month, and also ensures that all data for that month is available, assuming you're processing data. Running at five minutes to midnight on the last day of the month may see you missing anything that happens between then and midnight.

这将消除您可能遇到的任何麻烦,以确定哪一天是一个月的最后一天,并确保该月份的所有数据都是可用的,假设您正在处理数据。在一个月的最后一天,在午夜前五分钟跑步,你可能会错过从午夜到午夜之间发生的一切。

This is the usual way to do it anyway, for most end-of-month jobs.

不管怎样,对于大多数月末的工作来说,这是通常的做法。


If you still really want to run it on the last day of the month, one option is to simply detect if tomorrow is the first (either as part of your script, or in the crontab itself).

如果您仍然想在这个月的最后一天运行它,一个选项是简单地检测明天是否是第一天(作为脚本的一部分,或者作为crontab本身)。

So, something like:

所以,类似:

55 23 28-31 * * [[ "$(date --date=tomorrow +\%d)" == "01" ]] && myjob.sh

should be a good start, assuming you have a relatively intelligent date program.

如果你有一个相对智能的约会程序,这应该是一个好的开始。

If your date program isn't quite advanced enough to give you relative dates, you can just put together a very simple program to give you tomorrow's day of the month (you don't need the full power of date), such as:

如果你的约会程序不够先进,不能给你提供相对的约会日期,你可以制作一个非常简单的程序,给你一个月的明天(你不需要日期的全部力量),例如:

#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;
}

and then use (assuming you've called it tomdom for "tomorrow's day of month"):

然后使用(假设你把它叫做tomdom,表示“每月的明天”):

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

Though you may want to consider adding error checking since both time() and mktime() can return -1 if something goes wrong. The code above, for reasons of simplicity, does not take that into account.

尽管您可能需要考虑添加错误检查,因为如果出现问题,time()和mktime()都可以返回-1。由于简单性的原因,上面的代码没有考虑到这一点。

#2


39  

There's a slightly shorter method that can be used similar to one of the ones above. That is:

有一种稍微短一点的方法可以使用,类似于上面的方法。那就是:

[ $(date -d +1day +%d) -eq 1 ] && echo "last day of month"

Also, the crontab entry could be update to only check on the 28th to 31st as it's pointless running it the other days of the month. Which would give you:

此外,crontab条目可以更新为只检查28 - 31号,因为在这个月的其他日子运行它是没有意义的。这将给你:

0 23 28-31 * * [ $(date -d +1day +%d) -eq 1 ] && myscript.sh

#3


18  

Set up a cron job to run on the first day of the month. Then change the system's clock to be one day ahead.

在一个月的第一天设立一个cron作业。然后改变系统的时钟,让它提前一天。

#4


9  

What about this one, after Wikipedia?

*之后的这个呢?

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

#5


8  

Adapting paxdiablo's solution, I run on the 28th and 29th of February. The data from the 29th overwrites the 28th.

改编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

#6


5  

You could set up a cron job to run on every day of the month, and have it run a shell script like the following. This script works out whether tomorrow's day number is less than today's (i.e. if tomorrow is a new month), and then does whatever you want.

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

#7


4  

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

Check out a related question on the unix.com forum.

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

#8


4  

Some cron implementations support the "L" flag to represent the last day of the month.

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

If you're lucky to be using one of those implementations, it's as simple as:

如果您幸运地使用了其中的一种实现,那么简单如下:

0 55 23 L * ?

That will run at 11:55 pm on the last day of every month.

每个月的最后一天晚上11点55分。

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

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

#9


3  

For a safer method in a crontab based on @Indie solution (use absolute path to date + $() does not works on all crontab systems):

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

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

#10


3  

You can just connect all answers in one cron line and use only date command.

您可以将所有答案连接到一个cron行中,并且只使用date命令。

Just check the difference between day of the month which is today and will be tomorrow:

检查一下这个月的一天和明天的区别:

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

If these difference is below 0 it means that we change the month and there is last day of the month.

如果这些差值小于0,这意味着我们要改变月份,这是一个月的最后一天。

#11


3  

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

#12


1  

What about this?

这是什么?

edit user's .bashprofile adding:

编辑用户的.bashprofile添加:

export LAST_DAY_OF_MONTH=$(cal | awk '!/^$/{ print $NF }' | tail -1)

Then add this entry to crontab:

然后把这个条目添加到crontab:

mm hh * * 1-7 [[ $(date +'%d') -eq $LAST_DAY_OF_MONTH ]] && /absolutepath/myscript.sh

#13


-1  

For AWS Cloudwatch cron implementation (Scheduling Lambdas, etc..) this works:

对于AWS Cloudwatch cron实现(调度Lambdas等),这是有效的:

55 23 L * ? *

Running at 11:55pm on the last day of each month.

在每个月的最后一天晚上11点55分跑步。