이 스크립트는 두 인스턴스를 동시에 실행하는 대신 15초마다 프로그램을 실행합니까?

이 스크립트는 두 인스턴스를 동시에 실행하는 대신 15초마다 프로그램을 실행합니까?

존재하다https://unix.stackexchange.com/a/11105/674, Giles는 다음과 같이 썼습니다.

다음 crontab 줄은 some_job15초마다 시작됩니다.

* * * * * for i in 0 1 2; do some_job & sleep 15; done; some_job

스크립트에서는 작업이 15초 이상 걸리지 않을 것으로 가정합니다. 다음 약간 더 복잡한 스크립트는 시간이 너무 오래 걸릴 경우 다음 인스턴스를 실행하지 못하게 합니다. date 지원되는 %s형식(GNU 또는 Busybox 등) 에 의존하므로 Linux에서는 문제가 없습니다. crontab에 직접 입력하는 경우 %crontab 줄에 나타나는 대로 문자를 작성해야 합니다.\%

end=$(($(date +%s) + 45))
while true; do
  some_job &
  [ $(date +%s) -ge $end ] && break
  sleep 15
  wait
done
[ $(date +%s) -ge $(($end + 15)) ] || some_job

그러나 15초마다 작업을 실행해야 한다면 cron이 아마도 잘못된 접근 방식일 수 있다는 점을 지적하고 싶습니다. unice는 수명이 짧은 프로세스에 적합하지만 15초마다 프로그램을 시작하는 오버헤드는 무시할 수 없을 정도입니다(프로그램 요구 사항에 따라 다름). 애플리케이션을 계속 실행하고 15초마다 작업을 수행하도록 할 수는 없나요?

이 올바른지

  • 이 스크립트는 cron으로 실행하면 안 됩니다.

  • 이 스크립트는 지금부터 15초마다 실행되는 "some_job" 인스턴스를 제출하려고 시도하며 "some_job"을 실행하는 인스턴스가 이미 있는 경우 "some_job"의 다음 인스턴스가 제출되지 않도록 방지합니다.

break1분 내 45~59초 사이에 "some_job" 인스턴스가 처음 제출되면 스크립트가 실행됩니다. 그런 다음 스크립트는 while 루프에서 벗어나 건너뛰고 sleep인스턴스 wait실행이 완료되도록 합니다. 루프 외부의 다음 명령에서는 조건이 false가 되며(시간이 여전히 분당 45~59초이기 때문에) 스크립트는 "some_job"의 마지막 인스턴스를 제출합니다. 이제 "some_job" 인스턴스가 두 개 실행되고 있는데 이는 바람직하지 않습니다. 옳은?

이렇게 스크립트를 작성하면 어떨까요?

end=$(($(date +%s) + 60))
while true; do
  some_job &
  sleep 15
  wait
  [ $(date +%s) -ge $end ] && break
done

감사해요.

답변1

some_job설정을 사용하면 ( date; sleep 5; echo OK )15초마다 하나씩 총 4개의 인스턴스가 생성됩니다. 5초 지연(즉) 대신 20초 지연을 사용하면 ( date; sleep 20; echo OK )20초 간격으로 3개의 인스턴스를 시작할 수 있습니다.

귀하의 코드가 작동하지 않기 때문에 그런 식으로 작성할 수 없습니다.

그런데 Giles의 코드가 나에게도 작동하지 않습니다. (5개의 인스턴스가 있고 마지막 인스턴스는 네 번째 인스턴스가 완료되기 전에 시작됩니다.)

이것이 제가 생각하는 코드입니다. 5초의 작업으로 4번의 실행을 얻었습니다. 20초의 작업으로 두 번의 실행을 얻었습니다.

#!/bin/bash
#
echo START $(date)

some_job() { echo JOB BEGIN $(date); sleep 20; echo JOB END $(date); }

begin=$(date +%s)
interval=15
duration=60

while :
do
    some_job

    now=$(date +%s)
    [[ $now -ge $((begin + duration)) ]] && break

    rem=$(( (now - begin) % interval))
    [[ $rem -eq 0 ]] && rem=interval
    delay=$((interval - rem))

    [[ $((now + delay)) -ge $((begin + duration)) ]] && break
    sleep $delay
done

echo FINISH $(date)

작업이 완료된 후 이 코드는 모듈로 연산자를 사용하여 %다음 15초 간격을 결정합니다. 그런 다음 작업을 다시 시작하기 전에 해당 시간에 도달할 때까지 기다립니다.

관련 정보