매월 마지막 날 일정


10

나는 달의 마지막 날에 스크립트를 예약하라는 지시를 읽었습니다.

참고 :
영리한 독자는 매월 마지막 날에 실행할 명령을 설정하는 방법을 궁금해 할 수 있습니다. 매월 적용 할 dayofmonth 값을 설정할 수 없기 때문입니다. 이 문제는 리눅스와 유닉스 프로그래머들을 괴롭 히고 있으며 몇 가지 다른 해결책을 만들어 냈습니다. 일반적인 방법은 date 명령을 사용하여 내일 날짜가 01인지 확인하는 if-then 문을 추가하는 것입니다.

00 12 * * * if [`date +%d -d tomorrow` = 01 ] ; then ; command1

이렇게하면 매일 정오 12시에 해당 월의 마지막 날인지 확인하고, 그렇다면 cron이 명령을 실행합니다.

여기에 이미지 설명을 입력하십시오

어떻게 [`date +%d -d tomorrow` = 01 ]작동합니까?
상태가 정확 then; command1합니까?


그것이 말하는 그대로의 말입니까? 여기에 쓰여진 것처럼 실제로 작동하지 않습니다 .
Michael Homer

나는 Snapshot을 올렸다. @ MichaelHomer
Calculus

감사! 나는 그것을 일치시키기 위해 형식화를 피들 링했다. 그것은 여전히 ​​옳지 않지만 사진이 말하는 것이다.
마이클 호머

1
없어 ; endif?
danblack

작동하지 않습니다. 구문 오류가 포함됩니다. 공백이 [없고 fi끝이 없습니다 . 또한 %crontab에서 특별합니다.
Kusalananda

답변:


17

요약

올바른 코드는 다음과 같아야합니다.

#!/bin/sh
[ "$#" -eq 0 ] && echo "Usage: $0 command [args]" && exit 1
[ "$(date -d tomorrow +'%d')" = 01 ] || exit 0
exec "$@"

이 스크립트를 호출하면 end_of_month.shcron의 호출은 다음과 같습니다.

00 12 28-31 * * /path/to/script/end_of_month.sh command

그러면 스크립트 end_of_month는 28, 29, 30 및 31 일에 한해 (내일은 해당 월의 마지막 날임을 확인합니다) 실행합니다. 다른 날에는 월말을 확인할 필요가 없습니다.

오래된 게시물.

이것은 Richard Blum, Christine Bresnahan pp 442, Third Edition, John Wiley & Sons © 2015의 "Linux Command Line and Shell Scripting Bible"책에서 인용 한 것입니다.

예, 그것이 말하는 것이지만 그것은 잘못되었거나 불완전합니다.

  • 결산이 누락되었습니다 fi.
  • [다음 사이에 공간이 필요합니다 `.
  • 되어 강력 $ (...) 대신를 사용하는 것이 좋습니다 `…`.
  • 확장 과 같이 따옴표를 사용하는 것이 중요합니다."$(…)"
  • ;이후 에 추가 가 있습니다then

내가 어떻게 알아? (자, 경험 ☺)하지만 Shellcheck 시도 할 수 있습니다 . 책에서 별표 뒤에 코드를 붙여 넣으면 위에 나열된 오류와 "누락 된 세방"이 표시됩니다. Shellcheck에서 오류가없는 스크립트는 다음과 같습니다.

#!/bin/sh if [ "$(date +%d -d tomorrow)" = 01 ] ; then script.sh; fi

작성된 사이트는 "쉘 코드"이기 때문에 해당 사이트가 작동합니다. 그것은 많은 쉘에서 작동하는 구문입니다.

shellcheck에서 언급하지 않은 몇 가지 문제는 다음과 같습니다.

  • date 명령이 GNU 날짜 버전이라고 가정합니다. 값으로 -d허용 되는 옵션이 있는 옵션 tomorrow(busybox에는 -d 옵션이 있지만 내일은 이해하지 못하고 BSD에는 -d옵션이 있지만 "디스플레이"는 시간과 관련이 없습니다).

  • 형식을 설정하는 것이 좋습니다 모든 옵션 date -d tomorrow +'%d'.

  • cron 시작 시간은 항상 현지 시간으로, DST (일광 절약 시간)가 설정되거나 설정 해제 된 경우 작업이 정확한 요일보다 1 시간 늦게 시작될 수 있습니다.

우리가 한 것은 cron으로 호출 할 수있는 쉘 스크립트입니다. 다음과 같이 프로그램 또는 명령의 인수를 수락하도록 스크립트를 추가로 수정할 수 있습니다 (최종 올바른 코드).

#!/bin/sh
[ "$#" -eq 0 ] && echo "Usage: $0 command [args]" && exit 1
[ "$(date -d tomorrow +'%d')" = 01 ] || exit 0
exec "$@"

이 스크립트를 호출하면 end_of_month.shcron의 호출은 다음과 같습니다.

00 12 28-31 * * /path/to/script/end_of_month.sh command

그러면 스크립트 end_of_month는 28, 29, 30 및 31 일에 한해 (내일은 해당 월의 마지막 날임을 확인합니다) 실행합니다. 다른 날에는 월말을 확인할 필요가 없습니다.

올바른 경로가 포함되어 있는지 확인하십시오. cron 내부의 PATH는 사용자 PATH와 같지 않을 것입니다.

참고 있다는 것을 하나의 달 스크립트의 최종 테스트는 (아래 표시) 다른 많은 유틸리티 나 스크립트를 호출 할 수 있었다.

또한 cron이 전체 명령 행에서 생성하는 추가 문제점을 피할 수 있습니다.

  • Cron은 또는로 %인용하더라도 명령 행을 분할합니다 ( 여기서는 작품 만 해당 ). 그것은 cron 작업이 실패하는 일반적인 방법입니다.'"\

end_of_month.sh가짜 시간으로 스크립트 를 테스트하여 스크립트가 특정 날짜에 작동하는지 (월말까지 기다리지 않고) 작동하는지 테스트 할 수 있습니다 .

$ faketime 2018/10/31 ./end_of_month echo "Command will be executed...."
Command will be executed....

ast-open date(또는 dateksh93이 ast-open의 일부로 빌드 된 경우 ksh93의 내장)은 date -d tomorrow +%s또는 date +%s tomorrow)를 지원 합니다.
Stéphane Chazelas

2
경험에 따르면 일정 시간 동안 작업이 작동하지 않는 것을 발견하기 위해 월말까지 기다리는 것보다 가짜 시간으로 스크립트를 올바르게 테스트하는 것이 훨씬 낫다는 것이 입증되었습니다. * * * * * echo "$(date -u +'date %c')" >>~/testfile인용하는 것을 잊어 버렸기 때문에 작동하지 않는다는 것을 발견하는 것처럼 \%(매달 한 번만 시도하면 디버깅하기가 어려워집니다). @Kusalananda
Isaac

8

구문 오류가 수정되고 명령이 덜 장황하게 약간 수정되었다고 가정합니다.

00 12 28-31 * * [ "$( date -d tomorrow +\%d )" != "01" ] || command1

내일 날짜를 두 자리 숫자로 가져 오기 위해 (사용되는 date +%d -d tomorrowGNU라고 가정) 실행됩니다 date. 숫자가 아닌 경우 01, 다음 오늘 달의 마지막 날이 아니다. 이 경우, 시험은 성공하고 command1있다 하지 실행. 작업은 매월 마지막 날이 될 수있는 정오에 실행됩니다.

원래 명령 :

00 12 * * * if [`date +%d -d tomorrow` = 01 ] ; then ; command1

몇 가지 문제가 있습니다.

  • 뒤에 공백이 없습니다 [.
  • ;직접 후 then.
  • %cron 작업 스펙에서 특별하며로 \%참조 해야합니다 (참조 man 5 crontab).
  • fi끝에 일치하는 결승은 없습니다 if.

2
[ ... ] && command1대신에 사용 하는 데 따른 문제점 if...은 해당 월의 마지막 날이 아닌 날에는 크론 작업이 0이 아닌 종료 상태로 종료되고 실패 가보고되어야 할 수 있다는 것입니다. 사용 [ "$(...)" != 01 ] || command1은 문제를 피하는 또 다른 방법입니다.
Stéphane Chazelas

1
원래 코드의 또 다른 문제는이다 ;사이 thencommand1.
Stéphane Chazelas

@ StéphaneChazelas 하나의 라이너를 싫어하는 또 다른 이유는 읽기가 어렵습니다.
Kusalananda

DST 변경으로 인해 cron의 시작 시간이 이동하므로 명령의 연속 실행 간의 시간 차이는 정수 (24 시간) 일이 아닐 수 있습니다.
Isaac Isaac

3
@cat 따옴표 "나 따옴표를 '제외하고 \백분율 기호 %는 cron이 두 부분으로 줄을 나누도록합니다. 이것이 cron이 실패하는 일반적인 방법 중 하나입니다.
Isaac

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.