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