可以互相调用的脚本的共享锁定

可以互相调用的脚本的共享锁定

这是一个不寻常的问题,可能是不良设计的结果。如果有人能提出更好的建议,我很乐意听到。但现在我想“按原样”解决它。

有一堆交互脚本。为了问题的目的并不重要,为了完整起见,这些脚本在物理备用和快照备用之间切换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.sh参数调用 (eg) subordinate,例如

./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_LOCK,无需事先export.

  • 该方法类似于这个另一个答案,但在我看来,它有一个优点:无论您的脚本已经使用哪些变量以及如何使用,检查额外的变量都不会干扰,它很简单,相关代码可能完全独立。添加对附加命令行选项的支持可能并不那么容易(取决于您的脚本是否已经使用命令行选项)。

相关内容