using lockfiles in shell scripts (BASH)
- Details
- Parent Category: Linux
- Category: programming
- Published on Saturday, 31 October 2009 12:22
- Hits: 22833
using lockfiles in shell scripts (BASH)
If you want to be 100% sure that only 1 process accesses a resource at the same time, you can use the command "lockfile". Lockfile creates a semaphore file which you have to remove at the end with "rm -f". Lockfile waits 8 seconds and then retries if the file already exists.
example (without lockfile):
{chilicode}
#!/bin/bash
if [ -e number.txt ]; then
echo "File exists"
else
echo "File does not exists. Create file now."
echo 1 > number.txt
fi
a=$(/usr/bin/tail -n 1 number.txt)
if [ $a -gt 1 ]; then
a=$(/usr/bin/tail -n 1 number.txt)
/usr/bin/expr $a - 1 >> number.txt
fi
if [ $a -lt 2 ]; then
a=$(/usr/bin/tail -n 1 number.txt)
/usr/bin/expr $a + 1 >> number.txt
fi
{/chilicode}
The file "number.txt" should only contain the numbers 1 and 2. But, if you now run the script 1000 times in parallel
{chilicode}
# for a in {1..1000}; do ./script.sh & done
{/chilicode}
You will end up with something like:
{chilicode}
# cat number.txt |sort -n|uniq
-1
0
1
2
3
4
{/chilicode}
Some people might be tempted to do something like a hand-made lockfile:
{chilicode}
#!/bin/bash
if [ -e number.txt ]; then
echo "File exists"
else
echo "File does not exists. Create file now."
echo 1 > number.txt
fi
lock=0;
if [ -e script.lock ];then
lock=1
fi
while [ $lock -eq 1 ]
do
if [ -e script.lock ];then
lock=1
else
lock=0
fi
done
touch script.lock
a=$(/usr/bin/tail -n 1 number.txt)
if [ $a -gt 1 ]; then
a=$(/usr/bin/tail -n 1 number.txt)
/usr/bin/expr $a - 1 >> number.txt
fi
if [ $a -lt 2 ]; then
a=$(/usr/bin/tail -n 1 number.txt)
/usr/bin/expr $a + 1 >> number.txt
fi
rm -f script.lock
{/chilicode}
In our example this does not really work. Because if there is a context switch between the test (if [ -e script.lock ]) and the actual lock (touch script.lock) you will still end up with a mess in number.txt.
solution with lockfile:
{chilicode}
#!/bin/bash
if [ -e number.txt ]; then
echo "File exists"
else
echo "File does not exists. Create file now."
echo 1 > number.txt
fi
lockfile script.lock
a=$(/usr/bin/tail -n 1 number.txt)
if [ $a -gt 1 ]; then
a=$(/usr/bin/tail -n 1 number.txt)
/usr/bin/expr $a - 1 >> number.txt
fi
if [ $a -lt 2 ]; then
a=$(/usr/bin/tail -n 1 number.txt)
/usr/bin/expr $a + 1 >> number.txt
fi
rm -f script.lock
{/chilicode}
pros:
- 100% sure that no more than one script is allowed to access the file
- less code

