First let me show what works. If I use flock with the file path, it works.
Terminal 1:
[root@centos ~]# flock -x -n /tmp/foo.txt -c "sleep 100"
Terminal 2:
[root@centos ~]# flock -x -n /tmp/foo.txt -c "sleep 100"
[root@centos ~]# echo $?
1
The above output shows that I first acquire an exclusive lock on /tmp/foo.txt in the first terminal. Then in the second terminal, when I try to acquire a lock on the same file, it fails.
Now let me know what does not work. If I use flock with file descriptor, it does not work.
Terminal 1:
[root@centos ~]# { flock -x -n 100; sleep 100; } 100> /tmp/foo.txt
Terminal 2:
[root@centos ~]# { flock -x -n 100; sleep 100; } 100> /tmp/foo.txt
The above output shows that I first try to acquire a lock on /tmp/foo.txt
in the first terminal. Then in the second terminal, when I try to acquire a lock on the same file, it succeeds. I expected it to fail just like in the previous example. Why does it succeed?
You are using -n
which will terminate if the lock cannot be acquired immediately and flock
will fail with exit code 1. Therefore after you execute your the code in the first terminal, it sleeps for 100 seconds. Next when you execute the same in another terminal, flock
fails and returns 1, but because there is a ;
and you do not do anything with the return code, the shell simply continues to execute the next statement and sleeps for 100 seconds.
Therefore you need to take decision on the return code of flock as below.
( flock -x -n 100 || exit 55; sleep 100; ) 100> /tmp/foo.txt
Now if you execute the above line in one terminal it will sleep for 100 seconds. Next if you run the code on another terminal it will immediately return to prompt. Do an echo $?
and you will see that it has returned 55
as we wanted to return using the ||
.
What the ||
does is short-circuiting. If flock
returns 0
as in normal exit which is a true value for the shell, it will not execute the right hand side of the expression and therefore go to the next statement. If the return value is 1
which is a false for the shell, it will continue to evaluate the right hand side expression which is exit 55
and therefore exit. You can do this by if-then-fi
also.
Also note that I have used brackets ()
instead of curly braces {}
. This is because, if you use the curley-braces then the commands will be executed in the current shell and if you use exit, then it will exit from the current shell. A bracket will create a subshell, therefore doing an exit
from there terminates the subshell and gets back you to your original shell.
It worked for your first example using -c
because there you have the single command enclosed within the flock
argument. Therefore if flock
is unable to acquire the lock it will simply not execute the statement and terminate.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With