如何确保 bash 脚本只运行一个实例?

如何确保 bash 脚本只运行一个实例?

不需要额外工具的解决方案将是首选。

答案1

几乎就像 nsg 的答案:使用锁目录。在 linux、unix 和 *BSD 以及许多其他操作系统下,目录创建是原子的。

if mkdir -- "$LOCKDIR"
then
    # Do important, exclusive stuff
    if rmdir -- "$LOCKDIR"
    then
        echo "Victory is mine"
    else
        echo "Could not remove lock dir" >&2
    fi
else
    # Handle error condition
    ...
fi

您可以将锁定 sh 的 PID 放入锁定目录中的文件中以进行调试,但不要陷入认为可以检查 PID 以查看锁定进程是否仍在执行的陷阱。这条路上有很多竞争条件。

答案2

要添加到布鲁斯·艾迪格的回答,并受到启发这个答案,您还应该在清理中添加更多智能,以防止脚本终止:

#Remove the lock directory
cleanup() {
    if rmdir -- "$LOCKDIR"; then
        echo "Finished"
    else
        echo >&2 "Failed to remove lock directory '$LOCKDIR'"
        exit 1
    fi
}

if mkdir -- "$LOCKDIR"; then
    #Ensure that if we "grabbed a lock", we release it
    #Works for SIGTERM and SIGINT(Ctrl-C) as well in some shells
    #including bash.
    trap "cleanup" EXIT

    echo "Acquired lock, running"

    # Processing starts here
else
    echo >&2 "Could not create lock directory '$LOCKDIR'"
    exit 1
fi

答案3

确保 bash 脚本的单个实例运行的另一种方法是:

#! /bin/bash -

# Check if another instance of script is running
if pidof -o %PPID -x -- "$0" >/dev/null; then
  printf >&2 '%s\n' "ERROR: Script $0 already running"
  exit 1
fi

...

pidof -o %PPID -x -- "$0"如果现有脚本已经在运行,则获取其 PID;如果没有其他脚本正在运行,则以错误代码 1 退出


¹ 好吧,任何同名的进程......

答案4

这可能太简单了,如有错误,请指正。还不够简单ps吗?

#!/bin/bash 

me="$(basename "$0")";
running=$(ps h -C "$me" | grep -wv $$ | wc -l);
[[ $running > 1 ]] && exit;

# do stuff below this comment

相关内容