lock

最後更新: 2017-12-20

目錄

 


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