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.