Мне нужно создать задание CRON, которое будет выполняться в последний день каждого месяца. Я создам его с помощью cPanel.
Любая помощь приветствуется. Спасибо
Мне нужно создать задание CRON, которое будет выполняться в последний день каждого месяца. Я создам его с помощью cPanel.
Любая помощь приветствуется. Спасибо
Ответы:
Возможно, самый простой способ - просто выполнить три отдельных задания:
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
и измените сценарий для обработки данных за предыдущий месяц.
Это устраняет любые проблемы, с которыми вы можете столкнуться при определении последнего дня месяца, а также гарантирует, что все данные за этот месяц будут доступны, если вы обрабатываете данные. Если вы бегаете без пяти минут до полуночи в последний день месяца, вы можете пропустить все, что происходит с этого времени до полуночи.
В любом случае это обычный способ сделать это для большинства работ в конце месяца.
Если ты все еще действительно хотите запустить его в последний день месяца, один из вариантов - просто определить, будет ли завтра первым (либо как часть вашего скрипта, либо в самом 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
если что-то пойдет не так. В приведенном выше коде для простоты это не учитывается.
Есть более короткий метод, который можно использовать, аналогичный одному из описанных выше. То есть:
[ $(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
/bin/sh: -c: line 1: unexpected EOF while looking for matching ')'
.
[ $(date -d +1day +\%d) -eq 1 ] && run_job
posix
а дата POSIX не поддерживает "-d +1day"
: - \ Более сложным (и уродливым) решением было бы:[ `date +\%d` -eq `cal | xargs echo | awk '{print $NF}'` ] && myscript.sh
Настройте задание cron для запуска в первый день месяца. Затем измените системные часы на один день вперед.
Адаптируя решение 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
,29
.
55 23 28 2
?
Вы можете настроить задание cron для запуска каждый день месяца и запустить сценарий оболочки, как показано ниже. Этот сценарий определяет, будет ли номер завтрашнего дня меньше сегодняшнего (т.е. если завтра новый месяц), а затем делает все, что вы хотите.
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
Некоторые реализации cron поддерживают флаг «L» для обозначения последнего дня месяца.
Если вам повезло использовать одну из этих реализаций, это очень просто:
0 55 23 L * ?
Это будет происходить в 23:55 в последний день каждого месяца.
http://www.quartz-scheduler.org/documentation/quartz-1.x/tutorials/crontrigger
#########################################################
# 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"
Для реализации cron AWS Cloudwatch (планирование лямбда-выражений и т. Д.) Это работает:
55 23 L * ? *
Запуск в 23:55 в последний день каждого месяца.
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
Как насчет этого?
редактировать .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
Последний день месяца может быть 28-31 в зависимости от того, какой сейчас месяц (февраль, март и т. Д.). Однако в любом из этих случаев следующий день всегда является 1-м числом следующего месяца. Таким образом, мы можем использовать это, чтобы всегда запускать какое-то задание в последний день месяца, используя приведенный ниже код:
0 8 28-31 * * [ "$(date +%d -d tomorrow)" = "01" ] && /your/script.sh