Мне нужно создать задание 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
и измените 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
, если что-то пойдет не так. Приведенный выше код, по соображениям простоты, не учитывает этого.
Там немного более короткий метод, который можно использовать аналогично одному из приведенных выше. То есть:
[ $(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
Настройте задание cron для запуска в первый день месяца. Затем измените системные часы на один день вперед.
Как насчет этого, после Википедии?
55 23 L * * /full/path/to/command
Адаптация решения 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
Вы можете настроить задание 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
00 23 * * * [[ $(date +'%d') -eq $(cal | awk '!/^$/{ print $NF }' | tail -1) ]] && job
Ознакомьтесь с связанным вопросом на форуме unix.com.
Некоторые реализации cron поддерживают флаг L для представления последнего дня месяца.
Если вам повезло использовать одну из этих реализаций, это просто:
0 55 23 L * ?
Это будет работать в 11:55 вечера в последний день каждого месяца.
http://www.quartz-scheduler.org/documentation/quartz-1.x/tutorials/crontrigger
Вы можете просто подключить все ответы в одной линии cron и использовать только команду date
.
Просто проверьте разницу между днем месяца, который сегодня и будет завтра:
0 23 * * * root [ $(expr $(date +\%d -d '1 days') - $(date +\%d) ) -le 0 ] && echo true
Если эти различия ниже 0, это означает, что мы меняем месяц и последний день месяца.
Для более безопасного метода в crontab на основе решения @Indie (использование абсолютного пути к date
+ $()
не работает во всех системах crontab):
0 23 28-31 * * [ `/bin/date -d +1day +\%d` -eq 1 ] && myscript.sh
#########################################################
# 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"
Как насчет этого?
изменить пользователя .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