Задача Cron для работы в последний день месяца

Мне нужно создать задание cron, которое будет работать в каждый последний день месяца. Я создам его из cpanel.

Любая помощь приветствуется. Благодаря

Ответ 1

Возможно, самый простой способ - просто выполнить три отдельных задания:

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

Это будет работать 28 февраля, хотя даже в високосные годы, если это проблема, вам нужно найти другой способ.


Однако, как правило, как существенно проще, так и правильно запускать работу как можно скорее в первый день каждого месяца, с чем-то вроде:

0 0 1 * * myjob.sh

и измените script для обработки данных предыдущего месяца.

Это устраняет любые трудности, с которыми вы можете столкнуться, когда выяснится, какой день последний месяц, а также обеспечивает доступность всех данных за этот месяц, если вы работаете с данными. За пять минут до полуночи в последний день месяца вы можете видеть, что вы пропускаете что-либо, что происходит между полуденным и днем.

Это обычный способ сделать это в любом случае для большинства заданий на конец месяца.


Если вы все еще хотите запустить его в последний день месяца, один из них - просто определить, будет ли завтра первым (либо как часть вашего script, либо самого 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, если что-то пойдет не так. Приведенный выше код, по соображениям простоты, не учитывает этого.

Ответ 2

Там немного более короткий метод, который можно использовать аналогично одному из приведенных выше. То есть:

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

Ответ 3

Настройте задание cron для запуска в первый день месяца. Затем измените системные часы на один день вперед.

Ответ 4

Как насчет этого, после Википедии?

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

Ответ 5

Адаптация решения paxdiablo, я запускаю 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

Вы можете настроить задание cron для запуска в каждый день месяца и запустить оболочку script, как показано ниже. Этот script определяет, будет ли число завтрашнего дня меньше, чем сегодня (т.е. Если завтра будет новый месяц), а затем сделает все, что вам нужно.

TODAY=`date +%d`
TOMORROW=`date +%d -d "1 day"`

# See if tomorrow day is less than today's
if [ $TOMORROW -lt $TODAY ]; then
echo "This is the last day of the month"
# Do stuff...
fi

Ответ 7

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

Ознакомьтесь с связанным вопросом на форуме unix.com.

Ответ 8

Некоторые реализации cron поддерживают флаг L для представления последнего дня месяца.

Если вам повезло использовать одну из этих реализаций, это просто:

0 55 23 L * ?

Это будет работать в 11:55 вечера в последний день каждого месяца.

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

Ответ 9

Вы можете просто подключить все ответы в одной линии cron и использовать только команду date.

Просто проверьте разницу между днем ​​месяца, который сегодня и будет завтра:

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

Если эти различия ниже 0, это означает, что мы меняем месяц и последний день месяца.

Ответ 10

Для более безопасного метода в crontab на основе решения @Indie (использование абсолютного пути к date + $() не работает во всех системах crontab):

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

Ответ 11

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

Как насчет этого?

изменить пользователя .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