最後更新: 2017-12-20
目錄
- flock
- Lock by create directory
- Script Snippet
flock
Install flock
# util-linux (Bultin)
# Normally “exec” in a shell script is used to turn over control of the script to some other program.
# open the file named in $lock for reading, and assign it file handle 200
exec 200>$lock
Coding
# locking _scriptname=$(basename $0) _pidfile="/var/run/$_scriptname.pid" exec 200>$_pidfile flock -xn 200 || { echo -n "another instance is running"; exit 1; } _pid=$$ echo $_pid echo $_pid 1>&200
exclusive lock
Nobody can read it, because it's still being written, and she's blocking your view
shared locks
1. They all can read what is on it, together => Multiple shared locks can co-exist.
2. If one or more shared locks already exist, exclusive locks cannot be obtained.
Other software
flom
distributed lock manager that can be used to synchronize shell commands
https://sourceforge.net/projects/flom/
Usage
flock [options] <file|directory> -c <command>
flock [options] <file descriptor number>
-n, --nb, --nonblock
Fail rather than wait if the lock cannot be immediately acquired.
-u, --unlock
Drop a lock. This is usually not required, since a lock is automatically
dropped when the file is closed.
-s, --shared
Obtain a shared lock, sometimes called a read lock.
-x, -e, --exclusive
Obtain an exclusive lock, sometimes called a write lock. (Default)
-c, --command command
Pass a single command, without arguments, to the shell with -c
i.e.
flock -s /tmp -c cat
Lock by create directory
用 create Directory 可能解決 touch file 不是 atomic operation 的問題
說明:
當 Dir 存在時, 如果再 mkdir 說會有以下 Err
error "mkdir: cannot create directory ‘/var/lock/mylock’: File exists"
而重複 touch file 就沒有任何 Err !!
* The syscall under mkdir is guarenteed to work atomicly in all cases
lockDir=/tmp/mylock if mkdir $lockDir; then echo "Your Job Here" >&2 rmdir $lockDir else echo "Lock failed - exit" >&2 exit 1 fi
Script Snippet
my-cron-job.sh
MyName=my-cron-job Script="my.php" Timeout=1 [email protected] #### Code #### LockDir=/var/lock/${MyName}.lck LogFile=/tmp/${MyName}.log ls -ld $LockDir; date # for debug if [ -d $LockDir ]; then echo "`date` - Lock exist: $LockDir" | tee -a $LogFile | cat if test "`find $LockDir -type d -mmin +$Timeout`"; then echo "Lock timeout. mail to admin" echo "Lock over $Timeout min." | mail -s $MyName $Admin fi else if mkdir $LockDir; then echo "Locking succeeded" >&2 /usr/bin/php $Script &>> $LogFile rmdir $LockDir && echo "Unlocking succeeded" else echo "Locking failed - exit" >&2 exit 1 fi fi