Using lock files in a bash shell script

Wrote this script recently – I had written a simple shell script that updated an HTML page with its output, then realised it would be all too easy for simultaneous writes to clobber the file.

This kind of concurrency can & should really be solved properly by using a database obviously, but it got me thinking and playing around and I ended up with the below – it’s clearly very “happy path” with loads of room for improvements – please feel free to suggest some or add to it 🙂


#!/bin/bash

#
# Example script that uses lock files to avoid concurrent writes
# TODO: loads more validation and error handling!
#
# www.DonaldSimpson.co.uk
# 25th May 2011

setup_lockfile(){
# set name of this program's lockfile:
MY_NAME=`basename $0`
LOCKFILE=/tmp/lock.${MY_NAME}.$$
# MAX_AGE is how long to wait until we assume a lock file is defunct
# scary stuff, with loads of scope for improvement...
# could use fuser and see if there is a process attached/not?
# maybe check with lsof? or just bail out?
MAX_AGE=5
echo "My lockfile name is ${LOCKFILE}"
sleep 1
}

check_lock(){
# Check for an existing lock file
while [ -f /tmp/lock.${MY_NAME}* ]
do
# A lock file is present
if [[ `find /tmp/lock.* -mmin +${MAX_AGE}` > "0" ]]; then
echo "WARNING: found and removing old lock file...`ls /tmp/lock.${MY_NAME}*`"
rm -f /tmp/lock.${MY_NAME}*
else
echo "A recent lock file already exists : `ls /tmp/lock.${MY_NAME}* | awk -F. {'print $2"."$3", with PID: " $4'}`"
echo "Will wait until the lock file is over ${MAX_AGE} minutes old then remove it..."
fi
sleep 5
done
}

create_lock(){
# ok to carry on... create a lock file - quickly ;-)
touch ${LOCKFILE}
# check we managed to make it ok...
if [ ! -f ${LOCKFILE} ]; then
echo "Unable to create lockfile ${LOCKFILE}!"
exit 1
fi
echo "Created lockfile ${LOCKFILE}"
}

cleanup_lock(){
echo "Cleaning up... "
rm -f ${LOCKFILE}
if [ -f ${LOCKFILE} ]; then
echo "Unable to delete lockfile ${LOCKFILE}!"
exit 1
fi
echo "Ok, lock file ${LOCKFILE} removed."
}

setup_lockfile
check_lock
create_lock

# Any calls to exit() from here on should first call cleaup_lock
# Do main processing tasks here...
sleep 20

# All Done.
cleanup_lock

3 thoughts on “Using lock files in a bash shell script”

Leave a Reply