最近我不得不创建自己的“flock”函数,因为我正在编写的脚本需要使用TRAP
,而这个命令不能与flock命令一起使用。
以下是代码:
#!/bin/bash
flock() {
local lock_name lock_path lock_pid check_pid script_arg script_source script_pid
lock_name="${1}"
script_pid="$$"
script_source="${BASH_SOURCE[0]}"
script_arg=("${BASH}" "${script_source}")
lock_path="$(dirname -- "$(realpath "${script_source[0]}}")")/${lock_name}_flock"
for ((i=0;i<${#BASH_ARGV[@]}; i++)); do
script_arg+=("${BASH_ARGV[~i]}")
done
if [[ -f "${lock_path}" ]]; then
read -r lock_pid < "${lock_path}" > /dev/null 2>&1
if [[ -n "${lock_pid[0]}" ]]; then
check_pid=$(ps -eo pid,cmd \
| awk -v a="${lock_pid}" -v b="${script_arg[*]}" '$1==a && $2!="awk" && index($0,b) {print $1}')
if [[ -n "${check_pid}" ]]; then
printf "%s\n" "Script is already running"
exit 0
fi
fi
fi
read -r check_pid < <(ps -eo pid,cmd | awk -v a="${script_arg[*]}" '$2!="awk" && index($0,a) {print $1}')
if [[ "${script_pid}" -ne "${check_pid[0]}" ]]; then
printf "%s\n" "Race condition prevented"
exit 0
fi
printf '%s' "${script_pid}" | tee "${lock_path}" > /dev/null 2>&1
}
要使用这个功能,只需添加函数,然后跟上您想要锁定文件的名称。
flock script_name
解释
该函数使用
BASH
,
BASH_SOURCE
和
BASH_ARGV
来创建进程状态下CMD列的外观。
例如:
./test.sh arg1 arg2 "this arg3"
CMD:
/bin/bash ./test.sh arg1 arg2 this arg3
然后,我们使用进程状态来仅显示与CMD匹配的任何项目,除此之外,我们将它们所有的PID放入一个数组中。
接下来,我们仅返回该数组的第一个值,并将其与脚本的PID进行比较,如果脚本的PID与我们的数组中的第一个PID不匹配,则退出,否则我们将脚本的PID存储在我们的锁定文件中。
如果锁定文件已经存在并包含现有的PID,则该函数将检查脚本是否仍在运行,方法是通过搜索PID和CMD值,如果正在运行,则退出,否则锁定文件中的PID将更新为新的PID。
该函数不仅可以防止竞争条件,而且即使系统崩溃,它也会继续工作,因为它不依赖于锁定文件来确定脚本是否在运行。
扩展为 shell 的进程 ID。在子 shell 中,它扩展为调用 shell 的进程 ID,而不是子 shell 的进程 ID。
一个数组变量,其成员是对应的 shell 函数名在 FUNCNAME 数组变量中定义的源文件名。shell 函数 ${FUNCNAME[$i]} 在文件 ${BASH_SOURCE[$i]} 中定义并从 ${BASH_SOURCE[$i+1]} 调用
一个包含当前bash执行调用堆栈中所有参数的数组变量。最后一个子例程调用的参数位于堆栈顶部;初始调用的第一个参数位于底部。当执行子例程时,所提供的参数被推入BASH_ARGV。仅当处于扩展调试模式时(请参阅Shopt内置程序的extdebug选项的描述),shell才设置BASH_ARGV。在脚本开始执行之后设置extdebug或在未设置extdebug的情况下引用此变量可能导致不一致的值。
BASH_ARGV
以相反的顺序返回参数。为了解决这个问题,在函数中运行以下代码,感谢
用户232326的帖子,它适用于bash 4.2+。
for ((i=0;i<${
script_arg+=("${BASH_ARGV[~i]}")
done
util-linux
中的flock
。 - Ben Grimmif ln numbers numbers.lock
测试可以防止同时更新;在if
语句体中没有竞争条件。 - Jonathan Leffler