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): #!/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
The file "number.txt" should only contain the numbers 1 and 2. But, if you now run the script 1000 times in parallel # for a in {1..1000}; do ./script.sh & done
You will end up with something like: # cat number.txt |sort -n|uniq -1 0 1 2 3 4
Some people might be tempted to do something like a hand-made lockfile: #!/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 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: #!/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
pros:- 100% sure that no more than one script is allowed to access the file
- less code
|