3 일마다 문자 그대로 bash 스크립트 실행


8

3 일마다 문자 그대로 쉘 스크립트를 실행하고 싶습니다. crontab과 함께 사용하면 01 00 */3 * *실제로 31 일에 실행되고 한 달의 1 일에 다시 실행되므로 조건을 충족하지 못합니다. */3구문은 1,4,7 ... 25,28,31 말과 동일합니다.

스크립트 자체가 조건을 확인하고 3 일이 지났 으면 종료하는 방법이 있어야합니다. 따라서 crontab은 매일 스크립트를 실행하지만 스크립트 자체는 3 일이 지 났는지 확인합니다.

심지어 일부 코드를 찾았지만 구문 오류가 발생하여 도움을 주시면 감사하겠습니다.

if (! (date("z") % 3)) {
     exit;
}

main.sh: line 1: syntax error near unexpected token `"z"'
main.sh: line 1: `if (! (date("z") % 3)) {'

4
정확하게 무슨 뜻입니까? 어떻게 작동 */3하지 않습니까? "3 일이 지난 경우": 3 일이 지난 후? 제발 편집 질문을하고 명확하게.
terdon

4
말 그대로 말 그대로? 이것은 x / y 질문처럼 보이며 실제로하려는 일에 대해 이야기하고 싶을 수도 있습니다. crontab이 스크립트를 실행하지 못하게하려고합니까?
Journeyman Geek

1
crontab 솔루션이 작동하지 않는 이유를 설명하기 위해 질문을 편집했습니다.
Taavi

같은 뭔가 date("z") % 3 == 0비슷한 문제로 고통 것입니다 : 조건이 12 월 윤년의 일부 않는 것을 년 12 월 29 일 및 1월 3일 사이의 사일에 대한 잘못된 것입니다.
Rhymoid

답변:


12

마지막 실행이 아직 특정 시간 전이 아닌 경우 즉시 스크립트를 중단하고 종료하려면이 방법을 사용하면 마지막 실행 날짜 및 시간을 저장하는 외부 파일이 필요합니다.

Bash 스크립트 상단에 다음 행을 추가하십시오.

#!/bin/bash

# File that stores the last execution date in plain text:
datefile=/path/to/your/datefile

# Minimum delay between two script executions, in seconds. 
seconds=$((60*60*24*3))

# Test if datefile exists and compare the difference between the stored date 
# and now with the given minimum delay in seconds. 
# Exit with error code 1 if the minimum delay is not exceeded yet.
if test -f "$datefile" ; then
    if test "$(($(date "+%s")-$(date -f "$datefile" "+%s")))" -lt "$seconds" ; then
        echo "This script may not yet be started again."
        exit 1
    fi
fi

# Store the current date and time in datefile
date -R > "$datefile"

# Insert your normal script here:

의미있는 가치를 설정하고 필요에 datefile=따라 가치를 조정하는 것을 잊지 마십시오 seconds=( $((60*60*24*3))3 일로 평가).


별도의 파일을 원하지 않으면 스크립트의 수정 타임 스탬프에 마지막 실행 시간을 저장할 수도 있습니다. 그러나 스크립트 파일을 변경하면 3 카운터가 재설정되고 스크립트가 성공적으로 실행 된 것처럼 처리됩니다.

이를 구현하려면 아래의 스 니펫을 스크립트 파일 맨 위에 추가하십시오.

#!/bin/bash

# Minimum delay between two script executions, in seconds. 
seconds=$((60*60*24*3))

# Compare the difference between this script's modification time stamp 
# and the current date with the given minimum delay in seconds. 
# Exit with error code 1 if the minimum delay is not exceeded yet.
if test "$(($(date "+%s")-$(date -r "$0" "+%s")))" -lt "$seconds" ; then
    echo "This script may not yet be started again."
    exit 1
fi

# Store the current date as modification time stamp of this script file
touch -m -- "$0"

# Insert your normal script here:

다시, 필요에 따라 가치를 조정하는 것을 잊지 마십시오 seconds=( $((60*60*24*3))3 일로 평가).


예, 특정 프로그램의 마지막 호출을 기록하려면 일종의 외부 데이터 저장소가 필요하며 파일 시스템이이를위한 확실한 선택입니다.
Kilian Foth

날짜를 저장할 필요조차 없습니다. 매번 파일을 터치하고 타임 스탬프를 확인하십시오.
djsmiley2kStaysInside

@ djsmiley2k 그렇습니다. 스크립트 파일을 수동으로 수정하면 지연이 재설정되는 위험이 허용되는 경우 수정 시간 소인을 사용할 수도 있습니다. 나는 그것을 내 대답에 추가했다.
바이트 사령관

현재 타임 스탬프를 사람이 읽을 수있는 날짜 대신 파일에 저장하면 약간의 시간을 절약 할 수 있으므로를 사용하여 경과 시간을 얻을 수 있습니다 $[ $(date +%s) - $(< lastrun) ]. 스크립트가 하루에 한 번 cron에서 실행되면 필요한 시간 간격에 약간의 여유를 추가하여 스크립트 실행이 몇 초 지연되면 다음 시간이 하루 종일 건너 뛰지 않습니다. 71 시간이 오틸을 지 났는지 매일 확인합니다.
ilkkachu

날짜 파일이있는이 마법사는 실제로 작동했습니다. 대단히 감사합니다!
Taavi

12

Cron은 실제로 이것에 대한 잘못된 도구입니다. 라는 일반적으로 사용하고 underloved 도구 실제로 거기 있는 힘의 작품. at는 주로 대화식 사용을 위해 설계되었으며 누군가가 더 나은 방법을 찾을 것이라고 확신합니다.

필자의 경우 testjobs.txt에 실행중인 스크립트가 있고 읽을 줄을 포함시킵니다.

예를 들어, 이것을 testjobs.txt로 사용합니다

echo "cat" >> foo.txt
date >> foo.txt
at now + 3 days < testjobs.txt

나는 당신의 쉘 스크립트 일 수있는 두 개의 무고한 명령을 가지고 있습니다. 나는 결정 론적 출력이 있는지 확인하기 위해 echo를 실행하고 명령이 필요에 따라 실행되는지 확인하는 날짜입니다. at이 명령을 실행하면 3 일 동안 새 작업을 추가하여 완료됩니다. (1 분 동안 테스트했습니다-작동합니다)

나는 확신 나는 내가에서 학대 한 방법으로 밖으로 호출 할 수 있습니다 합니다만, 명령 스케줄링에 대한 편리한 도구가 실행되도록 에서 이전 명령 다음에 한 번 또는 X 일.


3
같은 일이 at이 방법으로 더 나은 방법 나가요 문제를 보이지 않는 언제든지 수동으로 스크립트를 실행하는 것이, 당신은 모든-3 일의 또 다른 세트 추가 at작업을.
Dewi Morgan

1
+1이지만 @DewiMorgan이 지적한 것 외에 다른 문제는 하나의 스크립트가 실패하면 스크립트가 다음을 인식 할 때까지 모든 후속 스크립트가 시작되지 않는다는 것입니다 실패하고 다시 시작하십시오. 이것은 나쁘거나 때로는 좋을 수 있습니다 (예 : 더 이상 존재하지 않기 때문에 실패합니다 : 3 일 후에 다시 시도하지 않는 것이 좋습니다?). 그리고 매번 약간의 드리프트가 있습니다 ( at맨 위에 있으면 몇 밀리 초 , 또는 at긴 실행 스크립트의 맨 아래에 있으면 훨씬 더 많이 )
Olivier Dulac

에서 이메일을 보낼 수 있습니다 .... 실패에 대한 해결책 일 수 있습니다. atq와 atrm은 잘못된 작업을 컬링 할 수 있을까요? 이론적으로 특정 날짜를 스크립팅 할 수는 있지만 우아하지 않은 것으로 보입니다.
Journeyman Geek

따라서 다음 실행의 존재를 확인하는 cronjob이 있습니다. 없는 경우 3 일 동안 추가하고 경고합니다 (또는 즉시 실행 한 후 다시 확인).
djsmiley2kStaysInside

3

첫째, 위의 코드 조각은 잘못된 Bash 구문이며 Perl처럼 보입니다. 둘째, 숫자 시간대를 출력 하는 z매개 변수 date입니다. +%j요일 번호입니다. 당신이 필요합니다 :

if [[ ! $(( $(date +%j) % 3 )) ]] ;then
     exit
fi

그러나 당신은 여전히 ​​연말에 이상한 것을 보게 될 것입니다 :

$ for i in 364 365  1 ; do echo "Day $i, $(( $i % 3 ))"; done
Day 364, 1
Day 365, 2
Day 1, 1

파일에 카운트를 유지하고 테스트 / 업데이트하는 것이 더 좋을 것입니다.


1
펄이없는 date()기능 내장을하지만 같은 약간 보이는 PHP 날짜 () ( z") 올해의 날 (0부터 시작"됩니다)
ilkkachu

2

스크립트를 영구적으로 계속 실행할 수 있다면 다음을 수행 할 수 있습니다.

while true; do

[inert code here]

sleep 259200
done

이 루프는 항상 참이므로 항상 코드를 실행 한 다음 3 일 동안 기다렸다가 루프를 다시 시작하십시오.


왜 안돼 while true?
Jonathan Leffler

하! 잘 잡았습니다. 나는 그것을 오랫동안 사용할 필요가 없었습니다, 나는 그것이 존재하는 것을 잊었습니다. lol
mkingsbu

2
는 AS at솔루션이 스크립트 각 실행의 실행 시간 드리프트 것입니다. 물론 스크립트가 시작되고 3 일이 될 때까지 수면 시간을 절약하여 해결할 수 있습니다.
ilkkachu

2

cron 대신 anacron을 사용할 수 있으며 필요한 것을 정확하게 수행하도록 설계되었습니다. 맨 페이지에서 :

Anacron을 사용하여 일 단위로 빈도를 지정하여 주기적으로 명령을 실행할 수 있습니다. cron (8)과 달리 머신이 계속 실행되고 있다고 가정하지 않습니다. 따라서 하루 24 시간 실행하지 않는 컴퓨터에서 일반적으로 cron에 의해 제어되는 일별, 주별 및 월별 작업을 제어하는 ​​데 사용할 수 있습니다.

Anacron을 실행하면 구성 파일 (일반적으로 / etc / anacrontab)에서 작업 목록을 읽습니다 (anacrontab (5) 참조). 이 파일에는 Anacron이 제어하는 ​​작업 목록이 포함되어 있습니다. 각 작업 항목은 기간 (일), 지연 시간 (분), 고유 한 작업 식별자 및 쉘 명령을 지정합니다.

Anacron은 각 작업에 대해 지난 n 일 동안이 작업이 실행되었는지 확인합니다. 여기서 n은 해당 작업에 지정된 기간입니다. 그렇지 않은 경우 Anacron은 지연 매개 변수로 지정된 시간 (분) 동안 기다린 후 작업 쉘 명령을 실행합니다.

명령이 종료 된 후 Anacron은 해당 작업에 대한 특수 타임 스탬프 파일에 날짜를 기록하므로 다시 실행할시기를 알 수 있습니다. 시간 계산에는 날짜 만 사용됩니다. 시간이 사용되지 않습니다.


좋아, 나는 Anacron을 테스트 할 것이다. 그것이 그러한 마술을 할 수 있다면 왜 그렇게 과소 평가되었는지 궁금해
Taavi

실제 질문 : 왜 cron이 지금까지 더 나은 것으로 대체되지 않았습니까? fcron이 존재하며 systemd가 자체 솔루션을 개발하고 있다고 생각하지만 현재 상황을 파악하지 못했습니다.
Twinkles
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.