서로 호출할 수 있는 스크립트에 대한 공유 잠금

서로 호출할 수 있는 스크립트에 대한 공유 잠금

이는 특이한 문제이며 잘못된 설계로 인해 발생할 수 있습니다. 누구든지 더 나은 제안이 있으면 듣고 싶습니다. 하지만 이제는 "있는 그대로" 해결하고 싶습니다.

대화형 스크립트가 많이 있습니다. 질문의 목적에는 중요하지 않습니다. 완전성을 위해 이러한 스크립트는 Oracle 데이터베이스 대기 노드를 물리적 대기와 스냅샷 대기 간에 전환하고, 스냅샷 데이터베이스를 생성하고 보고 팀을 위한 일부 할당을 추가하고 오래된 보관 로그를 해제합니다. 과정 .

가지다:

  • delete_archivelogs.sh
  • switch_to_physical_standby.shdelete_archivelogs.sh, 그리고 결국 호출될 것입니다.
  • switch_to_snapshot_standby.sh
  • sync_standby.sh, 호출하고 switch_to_physical_standby.sh대기 상태가 따라잡을 때까지 기다린 다음 호출합니다.switch_to_snapshot_standby.sh

마지막 스크립트는 sync_standby.sh일반적으로 cron 작업에서 실행되지만 DBA가 결정한 경우 각 스크립트도 자유롭게 실행할 수 있어야 합니다.

각 스크립트에는 두 번 실행되는 것을 방지하는 잠금 파일 기반 보호(클러스터링을 통한)가 있습니다. 그러나 이러한 스크립트에는 실행 중에 switch_to_snapshot_standby.sh(개별적으로) 시작할 수 없는 공유 공통 잠금이 있어야 하므로 sync_standby.sh다른 스크립트가 작동하는 동안 DBA가 실수로 한 스크립트를 실행하지 않도록 해야 합니다.

일반적으로 모든 스크립트에서 동일한 잠금 파일을 구성합니다. 이 경우에는 sync_standby.sh잠금이 획득되면 호출된 스크립트가 실행되지 않으므로 이는 불가능합니다 .

이 경우 잠금을 공유하는 가장 좋은 방법은 무엇입니까? 잠금 코드를 건너뛰고 상위 스크립트 호출에서 이를 사용하도록 "명령줄" 스위치를 구현하는 것이 가능합니까?

답변1

스크립트 중 어느 것도 명령줄 옵션을 요구하지 않으면 명령줄 옵션을 사용하여 이 flock메커니즘을 사용할지 여부를 "슬레이브" 스크립트에 표시할 수 있습니다.

따라서 귀하의 예에서 스크립트는 다음 과 같은 인수(예:)를 sync_standby.sh사용하여 호출됩니다.switch_to_snapshot_standby.shsubordinate

./switch_to_snapshot_standby.sh subordinate

그런 다음 스크립트 switch_to_snapshot_standby.sh는 매개변수를 사용하여 호출되었는지 확인하고 flock이 경우 코드를 우회합니다.

if [[ "$1" != "subordinate" ]]
then
    flock # with your arguments
fi

subordinate스크립트가 명령줄 인수를 사용하는 경우 이 메커니즘을 사용할 수도 있지만 인수가 제공되었는지 확인하려면 분명히 정렬해야 합니다 .

답변2

모든 스크립트는 개인 환경 변수가 존재하는지 여부(실제로는 비어 있는지, 비어 있지 않은지)를 확인해야 합니다. 변수에 대해 사용되지 않은 이름을 선택하십시오. 변수가 존재하는 경우 스크립트는 이미 잠금(상속됨)을 보유하고 있다고 가정해야 합니다.

변수가 존재하지 않으면 스크립트는 잠금 획득을 시도해야 합니다. 성공하면 다른 스크립트가 해당 환경에서 변수를 가져오도록 해야 합니다.


개념의 증거

scrpt:

#!/bin/bash
(
  if [ -z "$HAVE_LOCK" ]; then
    flock 9 || exit 1
    export HAVE_LOCK=1
  fi

  date
  sleep 1
  [ "$RANDOM" -gt 3000 ] && ./scrpt
  echo done
) 9>/tmp/my-lock

./scrpt두 콘솔에서 거의 동시에 실행됩니다. 그 중 한 명은 자물쇠를 받게 됩니다. 그것은 계속해서 자신을 호출할 가능성이 높지만, 자손 중 누구도 멈추지 않을 것입니다. 결국에는 중지되고 다른 하나는 계속됩니다.

노트:

  • bash(아님 sh) 그냥 필요해서요 $RANDOM.

  • echo done./scrpt각 인스턴스에서 각각이 별도의 프로세스인지 확인하세요 . Bash가 이를 암시적으로 수행하는 것을 허용하지 않습니다 exec ./scrpt. Bash가 이를 수행한다고 말하는 것은 아니지만 기술적으로는 그렇게 한다고 생각하므로 이 예는 설득력이 없습니다.

  • export나는 잊어버릴 수 있도록 즉시 변수를 선택했습니다. 사전에 할 필요 없이 HAVE_LOCK=1 ./scrpt환경에서 아이를 운영하는 ./scrpt방법 입니다 .HAVE_LOCKexport

  • 방법은 다음과 유사합니다.이 다른 답변, 그러나 제 생각에는 장점이 있습니다. 스크립트가 이미 어떤 변수를 사용하고 있는지, 어떻게 추가 변수를 확인하는지에 상관없이 간단하고 관련 코드가 완전히 독립적일 수 있습니다. 추가 명령줄 옵션에 대한 지원을 추가하는 것은 그리 쉽지 않을 수 있습니다(스크립트가 이미 명령줄 옵션을 사용하는지 여부에 따라 다름).

관련 정보