매월 말일에 실행할 CRON 작업


95

매월 말일에 실행할 CRON 작업을 만들어야합니다. cPanel을 사용하여 만들겠습니다.

도움을 주시면 감사하겠습니다. 감사

답변:


183

아마도 가장 쉬운 방법은 세 가지 개별 작업을 수행하는 것입니다.

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

그러나 윤년에도 불구하고 2 월 28 일에 실행되므로 문제가 발생하면 다른 방법을 찾아야합니다.


그러나 일반적으로 다음과 같이 매월 1 일에 가능한 한 빨리 작업을 실행하는 것이 훨씬 쉽고 정확합니다 .

0 0 1 * * myjob.sh

그리고 처리 할 수있는 스크립트를 수정 이전 달의 데이터를.

이렇게하면 해당 월의 마지막 날짜를 파악하는 데 발생할 수있는 번거 로움이 제거되고 데이터를 처리한다고 가정 할 때 해당 월의 모든 데이터를 사용할 수 있습니다. 매월 마지막 날 5 분에서 자정까지 달리면 그 때부터 자정 사이에 발생하는 모든 것이 누락되는 것을 볼 수 있습니다.

이것은 대부분의 월말 작업에서이를 수행하는 일반적인 방법입니다.


당신은 여전히하면 정말 달의 마지막 날에 그것을 실행하려면, 하나의 옵션은 내일 (스크립트의 일부로하거나, 또는 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뭔가 잘못되면. 위의 코드는 단순성 때문에이를 고려하지 않았습니다.


7
그래, 마지막 날 대신에 매일 실행하는 것이 더 쉬울 수 있습니다. :)
Utku Dalmaz

1
실제로 매월 1 일. 다음은 PHP에서 코드가 어떻게 표시되는지 보여줍니다. $ date = new DateTime ( '2013-03-01'); $ date-> modify ( '-1 개월'); $ previousMonth = $ date-> format ( 'Y-m'); // $ previousMonth는 이제 2013-02입니다. 이전 달의 제품을 가져 오는 쿼리를 작성합니다.
Lamy

윤년 2 월 29 일 데이터가 손실 될 것입니다. 우리도 그것을 고려해야합니다. 아래의 Thunder Rabbit 답변은 윤년 2 월에 cron이 두 번 실행됩니다
Hari Swaminathan 2014

1
@Hari, 선호하는 솔루션은 매월 1 일에 실행하고 이전 달의 데이터를 수집하는 것입니다. 이 경우 2 월 29 일은 놓칠 수 없습니다.
paxdiablo 2014

1
윤년 고려 : 두 번 실행해도 괜찮다면 : 55 23 28,29 2 * myjob.sh
radiantRazor

52

위의 방법 중 하나와 비슷하게 사용할 수있는 약간 더 짧은 방법이 있습니다. 그건:

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

나는 이것을 crontab 항목으로 작동시킬 수 없었습니다 (내 생각에는 이스케이프해야합니다). 그러나 crontab에서 호출되는 쉘 스크립트에서는 잘 작동했습니다. 참고로 내가 얻은 오류는 /bin/sh: -c: line 1: unexpected EOF while looking for matching ')'.
Mark Rajcok 2014 년

13
이것은 훌륭하게 작동합니다. crontab 파일에서 %는 이스케이프되어야합니다. 그래서[ $(date -d +1day +\%d) -eq 1 ] && run_job
ColinM 2014 년

참으로 멋진 트릭! 하지만 문제는이 태그되었습니다 posixPOSIX 날짜는 지원하지 않습니다 "-d +1day": - \ A는 더 복잡 (못생긴) 솔루션은 다음과 같습니다[ `date +\%d` -eq `cal | xargs echo | awk '{print $NF}'` ] && myscript.sh
ckujau

15

매월 1 일에 실행되도록 크론 작업을 설정합니다. 그런 다음 시스템 시계를 하루 앞당기도록 변경합니다.


11
이는 시스템 시계가 항상 잘못된다는 것을 의미합니다. 죄송하지만 이로 인해 더 많은 문제가 발생할 것 같습니다. -1 그럼.
Rudy

70
이제 나는 갈릴레오가 어떻게 느꼈는지 압니다.
Tom Anderson

7
@iconoclast : 농담 이라기보다 공안이라고 생각하고 싶습니다.
Tom Anderson

14
나는 이것이 정말로 나쁘고 훌륭한 아이디어라고 생각합니다. 집에서 하지마, 애들 아
Pascal

11
@pascalbetz 오, 사람들은 집에서 할 수 있지만 직장에서는하지 말아야합니다.
Tom Anderson

14

위키피디아 이후 이건 어때?

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

글쎄, 어때? "crontab 파일의 잘못된 날짜 오류, 설치할 수 없습니다. 동일한 편집을 다시 시도 하시겠습니까?"
webjunkie 2012-07-17

12
분명히 말하면 위키피디아 항목에는 "L"이 비표준이라고 언급되어 있습니다.
sdupton 2013 년

10

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

4
물론, 작업 등이 :-) 처리있어 모든 데이터를 삭제와 같은 일부 파괴적인 측면하지 않는 한
paxdiablo

이것은 실제로 고통스럽지 않은 옵션 (최소한의 기술)이며, ,29.
Matt

@Matt : 음, crontab 항목에 따르면 4 년에 한 번 너무 일찍 실행된다는 뜻이 55   23   28    2아닙니까?
G-Man은 '모니카 복원'이라고 말합니다.

@ G-Man 네, 맞아요. 게다가 29 일에 두 번째로 실행했습니다.
Matt

8

매월 매일 실행되도록 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

오늘보다 적은지 확인하여 얻을 수있는 것이 무엇인지 잘 모르겠습니다. 1 일인지 확인 만하면됩니다. 매월 1 일이 2 일 또는 3
아닌 경우

7

@Indie 솔루션을 기반으로하는 crontab에서 더 안전한 방법 ( date+에 대한 절대 경로 사용 $()은 모든 crontab 시스템에서 작동하지 않음) :

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


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

5

AWS Cloudwatch cron 구현 (Lambda 예약 등)의 경우 다음과 같이 작동합니다.

55 23 L * ? *

매월 말일 11:55 pm에 실행됩니다.


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

unix.com 포럼 에서 관련 질문 을 확인하십시오 .


3

하나의 cron 줄에 모든 답변을 연결하고 date명령 만 사용할 수 있습니다.

오늘과 내일이 될 월의 차이를 확인하십시오.

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

이 차이가 0 미만이면 월을 변경하고 해당 월의 마지막 날이 있음을 의미합니다.


3
55 23 28-31 * * echo "[ $(date -d +1day +%d) -eq 1 ] && my.sh" | /bin/bash 

1
명령을 에코하고 bash에 파이핑하는 것이 cron으로 작업 할 때 가장 좋은 방법입니다. cron은 bash가 아닌 sh를 사용하기 때문입니다. bash가 'which bash'를 사용하고 있는지 확인하십시오. FreeBSD에서는 / usr / local / bin / bash이고 Linux에서는 / bin / bash입니다.
Donald Duck

2

이건 어때?

사용자 .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

0

월의 마지막 날은 월 (2 월, 3 월 등)에 따라 28-31 일 수 있습니다. 그러나이 두 경우 모두 다음 날은 항상 다음 달의 1 일입니다. 따라서 아래 코드를 사용하여 매월 마지막 날에 항상 작업을 실행하는 데 사용할 수 있습니다.

0 8 28-31 * * [ "$(date +%d -d tomorrow)" = "01" ] && /your/script.sh
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.