互いに呼び出すことができるスクリプトの共有ロック

互いに呼び出すことができるスクリプトの共有ロック

これは珍しい問題であり、誤った設計によって発生する可能性があります。誰でも良い提案があれば聞きたいです。しかし、今は「現状のまま」解決したいと思います。

インタラクティブなスクリプトがたくさんあります。質問の目的には重要ではありません。完全性のために、これらのスクリプトは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が決定した場合は各スクリプトも自由に実行できるはずです。

各スクリプトには、2回の実行を防ぐロックファイルベースの保護(クラスタリングによる)があります。ただし、これらのスクリプトには、実行中に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両方のコンソールでほぼ同時に実行されます。そのうちの1人は南京錠を受け取ります。それは自分自身を呼び出す可能性が高いですが、子孫のどれも停止しません。最終的には停止し、もう一つは続きます。

メモ:

  • bash(いいえsh)ただ必要です$RANDOM

  • echo done./scrpt各インスタンスで、それぞれが別々のプロセスであることを確認してください。 Bashがこれを暗黙的に実行することを許可しませんexec ./scrpt。 Bashがこれを行うとは言いませんが、技術的にはそうすると思うので、この例は説得力がありません。

  • export私は忘れられるようにすぐに変数を選択しました。事前にする必要なくHAVE_LOCK=1 ./scrpt環境で子どもを運営する./scrpt方法です。HAVE_LOCKexport

  • 方法は次のようになります。この他の答えしかし、私の考えには利点があります。スクリプトがすでにどの変数を使用しているか、どのように追加変数を確認するかに関係なく、単純で関連コードは完全に独立している可能性があります。追加のコマンドラインオプションのサポートを追加するのはそれほど簡単ではありません(スクリプトがすでにコマンドラインオプションを使用しているかどうかによって異なります)。

関連情報