不需要额外工具的解决方案将是首选。
答案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