代码
#!/bin/bash
## Copyright (C) 2009 Przemyslaw Pawelczyk <przemoc@gmail.com>
##
## This script is licensed under the terms of the MIT license.
## https://opensource.org/licenses/MIT
#
# Lockable script boilerplate
### HEADER ###
LOCKFILE="/var/lock/`basename $0`"
LOCKFD=99
# PRIVATE
_lock() { flock -$1 $LOCKFD; }
_no_more_locking() { _lock u; _lock xn && rm -f $LOCKFILE; }
_prepare_locking() { eval "exec $LOCKFD>\"$LOCKFILE\""; trap _no_more_locking EXIT; }
# ON START
_prepare_locking
# PUBLIC
exlock_now() { _lock xn; } # obtain an exclusive lock immediately or fail
exlock() { _lock x; } # obtain an exclusive lock
shlock() { _lock s; } # obtain a shared lock
unlock() { _lock u; } # drop a lock
### BEGIN OF SCRIPT ###
# Simplest example is avoiding running multiple instances of script.
exlock_now || exit 1
# Remember! Lock file is removed when one of the scripts exits and it is
# the only script holding the lock or lock is not acquired at all.
加锁过程
"/var/lock/
`basename $0
`"
: 根据当前脚本的名字,在/var/lock/
目录下创建一个临时文件eval "exec $LOCKFD>\"$LOCKFILE\"";
: 打开这个临时文件,并获得句柄(LOCKFD
)_lock xn
: 使用flock -xn $LOCKFD
获得文件句柄的排它锁(Exclusive Lock
),如果获取失败,则状态码非0
解锁过程
trap _no_more_locking EXIT
: 捕获脚本的退出事件(EXIT),当脚本退出时(Ctrl + C
、kill -s TERM $PID
、正常结束等, 不包括kill -9 $PID
),会执行_no_more_locking
_lock u; _lock xn && rm -f $LOCKFILE;
: 解锁,加锁(成功后)删除临时文件。_lock u
解锁,以便其他进程对临时文件加锁;_lock xn && rm -f $LOCKFILE
如果加锁成功,则删除临时文件,否则不删,因为此时有其他进程正在锁住临时文件。
注意
The flock command is part of the util-linux-ng package and is available from ftp://ftp.kernel.org/pub/linux/utils/util-linux-ng/. macOS系统中没有这个命令
参考
原文: What is the best way to ensure only one instance of a Bash script is running?