CRON 스크립트 CRON의 대기열 또는 대기열 역할을하는 CRON 스크립트?

StackOverflow https://stackoverflow.com/questions/226473

  •  03-07-2019
  •  | 
  •  

문제

나는 누군가가 이미 이것을 해결했다고 베팅하고있을 것입니다. 아마도 Google에 대한 잘못된 검색어를 사용하여 답을 알려주는데 여기에 내 상황이 있습니다.

실행하고 싶은 스크립트가 있지만 예약 할 때만 실행하고 한 번에만 실행하기를 원합니다. (스크립트를 동시에 실행할 수 없습니다)

이제 끈적 끈적한 부분은 내가 필요한 데이터와 예정된 시간을 가진 "myhappyschedule"이라는 테이블이 있다는 것입니다. 이 테이블은 동시에 여러 예약 시간을 가질 수 있으며 각 테이블은이 스크립트를 실행합니다. 따라서 본질적으로 스크립트가 발사 될 때마다 대기열이 필요하며마다 끝날 때까지 각각을 기다려야합니다. (때로는 스크립트가 때때로 몇 분 동안 실행하는 데 1 분이 걸릴 수 있습니다)

내가 생각하는 것은 5 분마다 myhappyschedule을 점검하고 예정된 것을 수집하는 스크립트를 만드는 것입니다. 다른 스크립트가 각 '작업'을 실행하거나 대기열에서 발생할 수있는 대기열에 넣습니다. 이 모든 것이 지저분하게 들립니다.

이것을 더 길게 만들기 위해 - 나는 사용자가 crontab을 편집하지 않고 myhappyschedule에서 예약 할 수 있도록 허용한다고 말해야합니다.

이것에 대해 무엇을 할 수 있습니까? 스크립트를 호출하는 파일 잠금 및 스크립트?

도움이 되었습니까?

해결책

열을 추가하십시오 exec_status 에게 myhappytable (아마도 time_started 그리고 time_finished, 의사 코드 참조)

X 분마다 다음 CRON 스크립트를 실행하십시오

CRON 스크립트의 의사 코드 :

[create/check pid lock (optional, but see "A potential pitfall" below)]
get number of rows from myhappytable where (exec_status == executing_now)
if it is > 0, exit
begin loop
  get one row from myhappytable
    where (exec_status == not_yet_run) and (scheduled_time <= now)
    order by scheduled_time asc
  if no such row, exit
  set row exec_status to executing_now (maybe set time_started to now)
  execute whatever command the row contains
  set row exec_status to completed
  (maybe also store the command output/return as well, set time_finished to now)
end loop
[delete pid lock file (complementary to the starting pid lock check)]

이런 식으로 스크립트는 먼저 명령이 실행되지 않는지 확인한 다음 주어진 순간에 더 이상 명령을 실행할 때까지 먼저 실행되지 않은 명령을 실행합니다. 또한 데이터베이스를 쿼리하여 어떤 명령이 실행되는지 확인할 수 있습니다.

잠재적 인 함정 : CRON 스크립트가 죽으면 예정된 작업은 "executing_now"상태로 유지됩니다. 그것이 시작과 끝에서의 PID 잠금 장치의 것입니다. CRON 스크립트가 제대로 종료되었는지 확인합니다. PIDLOCK 생성/점검의 의사 코드 :

if exists pidlockfile then
  check if process id given in file exists
  if not exists then
    update myhappytable set exec_status = error_cronscript_died_while_executing_this   
      where exec_status == executing_now
    delete pidlockfile
  else (previous instance still running)
    exit
  endif
endif
create pidlockfile containing cron script process id

다른 팁

스크립트 내부의 AT (1) 명령을 사용하여 다음 실행을 예약 할 수 있습니다. 종료되기 전에 다음 달리기 시간에 대해 MyHappySchedule을 확인할 수 있습니다. 당신은 정말로 Cron이 필요하지 않습니다.

나는 대기열 문제에 대한 해결책을 연구하는 동안이 질문을 발견했습니다. 다른 사람이 여기서 검색하는 이점은 내 해결책입니다.

이를 예약 할 때 작업을 시작하는 CRON과 결합하고 (동시에 실행할 예정이더라도) 설명 된 문제도 해결합니다.

문제


  • 스크립트의 최대 한 인스턴스가 실행되어야합니다.
  • 우리는 가능한 빨리 처리하기위한 요청을 큐를 원합니다.

즉. 스크립트에 파이프 라인이 필요합니다.

해결책:


모든 스크립트에 파이프 라인을 만듭니다. 작은 bash 스크립트를 사용하여 완료 (더 아래로).

스크립트를 호출 할 수 있습니다
./pipeline "<any command and arguments go here>"

예시:

./pipeline sleep 10 &
./pipeline shabugabu &
./pipeline single_instance_script some arguments &
./pipeline single_instance_script some other_argumnts &
./pipeline "single_instance_script some yet_other_arguments > output.txt" &
..etc

스크립트는 새로운 것을 만듭니다 명명 된 파이프 각 명령에 대해. 따라서 위는 이름이 지정된 파이프를 만듭니다. sleep, shabugabu, 그리고 single_instance_script

이 경우 초기 호출은 독자를 시작하고 실행됩니다. single_instance_script ~와 함께 some arguments 논쟁으로. 통화가 완료되면 독자는 다음 요청을 파이프에서 가져 와서 some other_arguments, 완료, 다음 등을 잡으십시오 ...

이 스크립트는 요청 프로세스를 차단하므로 백그라운드 작업 (& 마지막에) 또는 분리 된 프로세스로 부릅니다. at (at now <<< "./pipeline some_script")

#!/bin/bash -Eue

# Using command name as the pipeline name
pipeline=$(basename $(expr "$1" : '\(^[^[:space:]]*\)')).pipe
is_reader=false

function _pipeline_cleanup {
        if $is_reader; then
                rm -f $pipeline
        fi
        rm -f $pipeline.lock

        exit
}
trap _pipeline_cleanup INT TERM EXIT

# Dispatch/initialization section, critical
lockfile $pipeline.lock
        if [[ -p $pipeline ]]
        then
                echo "$*" > $pipeline
                exit
        fi

        is_reader=true
        mkfifo $pipeline
        echo "$*" > $pipeline &
rm -f $pipeline.lock

# Reader section
while read command < $pipeline
do
        echo "$(date) - Executing $command"
        ($command) &> /dev/null
done
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top