Shell Script Nuggets: Simulating File Locks
Shell scripts are often run sequentially and there’s usually little reason for synchronisation. However, there are occasions when you might want to run multiple shell scripts where these scripts contend for the same file. In such instances, it is necessary to lock the said file in order to avoid processing out-of-date data or worse, corrupting the file.
So how do we achieve this lock? There is no locking mechanism in the Unix Shell environment. All you have available are a collection of useful utilities. The obvious method that one might think of is to create a temporary file, and check for its existence before proceeding. If the temporary file exists, then the primary file is locked, otherwise it is free for the taking. Something of the following form:
if [ -f ${filename}.tmp ]; then
echo “File is locked”
else
:>${filename}.tmp
echo “File is free”
fi
While this method might seem to be the solution, it is flawed. If you think about it, a file lock works like a semaphore. The function that checks for availability and applies a semaphore lock should do so in a single unit of work. If you analyse the shell script above, you’ll realise that the check and lock application are done in two separate statements. This creates a race environment. Two processes may check the file lock, find the lock is free, and attempt to lock the file at the same time. Using the method above, there is a possibility that both processes will gain access to the file and cause some serious headaches.
So if we understand the concept of semaphore locks and that it is necessary to check and apply locks in one single work unit, do we have a means to do so from a shell script environment? The answer is, yes. The method is by using the Unix ln soft-link (ln -s) utility.
‘ln -s’ is exclusive. When invoked, it attempts to create a soft-link to a file (the file doesn’t really have to exist). Upon success, a soft-link file is created and the function returns zero (0). If the soft-link already exists, the function will fail and return a non-zero value (1). This basically fulfills all the requirements that are set forth by the semaphore lock concept. Now that we have a shell utility that does the necessary work, translating it into a locking mechanism is trivial.
file_lock () {
lockfile=”${1}.tmp”
action=”$2″case “$action” in
lock) # Check and apply a file lock if possible
ln -s whatever $lockfile
return $?
;;
unlock) # Remove the file lock
rm -f $lockfile
return $?
;;
esac# Return failure (for everything else)
return 1
}
Above is a simple example that encapsulates the lock mechanism within a reusable function that handles both locking and unlocking. The function takes two arguments. The first argument is the file that needs to be locked. The second argument is the action to be taken (either “lock” or “unlock”). You can of course modify it to handle more complex situations but usually, that’s all that’s required. The following is a quick example of its usage:
# Attempt to acquire file lock
while 1; do
file_lock myfile lock
if [ $? -eq 0 ]; then
break
fi
done# Do something with the file here
# Free the file lock
file_lock myfile unlock
Simple and sweet. You can embed the while loop within the file_lock function if you want to implement a block waiting lock mechanism. Possibilities are endless. The real lesson here is that semaphore locking IS possible within the shell environment by using ‘ln -s’. A secondary lesson is that shell scripting is not as wimpy as it looks.
Related posts:
Shell Script Nuggets: File Date Manipulation And Checking
Perl Scripting: Checking CPAN Module Versions
Shell Script Nuggets: Mathematic Computations
Tech: Rsync rulez!
Script Tips: ssh-key For Apache

Anon Said,
January 29, 2007 @ 4:14 pm
I get rather fidgety when I use the rm -f command. As someone once observed, it’s the most showstopping flaw in Un*x - that there’s no undo mechanism. I have learnt instead to move the file to a temp folder and then manually delete the contents (yes, using rm), or use Midnight Commander (mc) to buang sampah. I know that there are undo scripts around… just lazy to check them out lah :P
Soft-linking is also called a symbolic link or a symlink. :D
G: Yeah, soft linking is also known as symbolic linking. I hate using rm -f but it’s a convenience. I hate rm -rf even more. I’ve on occasion done rm -rf * on my user root and cried thereafter.