unix中将4个shell脚本依次同步到运行

Synchronizing four shell scripts to run one after another in unix

我有 4 个 shell 脚本来生成一个文件(比方说 param.txt),该文件被另一个工具(informatica)使用,当该工具完成处理时,它会删除 param.txt.

这里的目的是可以在不同的时间调用所有四个脚本让我们说 12:10 am,12:13 am,12:16 am,12:17 am。第一个脚本在 12:10am 运行并创建 param.txt 并触发使用 param.txt 的 informatica 进程。 Informatica 进程还需要 5-10 分钟才能完成并删除 param.txt。第二个脚本在 12:13 am 调用并等待 param.txt 不可用,当 informatica 进程删除它时,脚本 2 创建新的 param.txt 并再次触发相同的 informatica。另外 2 个脚本也会发生同样的情况。

我在所有 4 个 shell 脚本中使用 Until 和 sleep 命令来检查 param.txt 的不可用性,如下所示:

until [ ! -f "$paramfile" ]
do
    Sleep 10
done
<create param.txt file>

这里的问题是,有时当所有 4 个脚本开始时,第一个成功并生成 param.txt(因为之前没有 param.txt)和其他等待,但是当 informatica 进程完成并删除 param.txt,其余 3 个脚本或其中 2 个同时检查不可用性,其中一个创建它但都成功。我检查了四个脚本之间不同的休眠间隔组合,但几乎每次都会出现这种情况。

您正在经历典型的竞争条件。要解决此问题,您需要在 4 个脚本之间共享 "lock"(或类似的)。

有几种方法可以实现这一点。在 bash 中执行此操作的一种方法是使用 flock 命令,并将商定的文件名用作锁定。 flock man page 有一些类似这样的用法示例:

(
    flock -x 200  # try to acquire an exclusive lock on the file
    # do whatever check you want. You are guaranteed to be the only one
    # holding the lock
    if [ -f "$paramfile" ]; then
        # do something
    fi
) 200>/tmp/lock-life-for-all-scripts
# The lock is automatically released when the above block is exited

你也可以要求flock在无法获取锁的情况下立即失败,或者在超时后失败(例如打印"still trying to acquire the lock"并重新启动)。

根据您的用例,您还可以锁定 'informatica' 二进制文件(在这种情况下一定要使用 200<,以打开文件进行读取而不是(结束)写作)

您可以使用 GNU Parallel 作为计数信号量或互斥量,方法是将其作为 sem 而不是 parallel 调用。向下滚动到 this page 上的 Mutex

因此,您可以使用:

sem --id myGlobalId 'create input file; run informatica'
sem --id myGlobalId 'create input file; run informatica'
sem --id myGlobalId 'create input file; run informatica'
sem --id myGlobalId 'create input file; run informatica'

注意我已经指定了全局 id 以防您 运行 来自不同终端或 cron 的作业。如果您从一个终端启动所有作业,则没有必要这样做。

感谢您的宝贵建议。它确实帮助我从另一个维度思考。但是我没有提到我正在使用 Solaris UNIX,但我找不到与 flock 等效或类似的功能。我本可以要求团队安装一个实用程序,但与此同时我找到了解决此问题的方法。

我了解到 mkdir 函数本质上是原子的,而 'touch' 创建文件的命令不是(仍然没有完整的解释它是如何工作的)。这意味着一次只有 1 个脚本可以 create/delete 目录 'lockdir' 4 个中,其他 3 个必须等待。

while true;
do 
if mkdir "$lockdir"; then
   < create param file >

break;
fi
    Sleep 30
done