There are cases when you'd like to make sure the same script cannot be run twice at the same time. Maybe because it generates a lot of load on the server, or because it uses some other scarce resource.
Maybe you are test-driving a drone, and there is only one drone.
This is a sample script that use flock
on the script being executed in order to make
sure there are no two proccess running at the same time.
Non-blocking version
$PROGRAM_NAME
is a variable Ruby provides us and it has the filename of the current script in it.
We open that file for reading and then we use the flock
method of the File class to try to put an
exclusive lock LOCK_EX
on it. We are trying to put this lock on it in a non-blocking way: LOCK_NB
.
If this is the first instance of the script the flock
will be successful. It will return true
and thus or code can continue printing the current process-id ($$
) and then going into the real process
which is represented by a call to sleep
in our code.
If we try to run the same script again, while the first instance is still running (sleeping), then
the flock
will not succeed. Because we made the call non-blocking it will return immediately with a false
value. In that case we complain an exit the script.
f = File.open($PROGRAM_NAME, 'r')
if (not f.flock(File::LOCK_EX | File::LOCK_NB))
puts "Another instance is already running"
exit
end
puts "Running #{$$}"
sleep 10
That's it. You can try it by running the script in one terminal and while it is still running, switching to another terminal and try running it there too. It will return immediately.
Blocking version
If we omit the LOCK_NB
from the call to flock
then the call to flock
will wait for the lock to be released by the other process. Once it is done the flock in the second process will
return and that instance will run too.
In this case there is no need for the if
statement as the flock
will wait till it can lock.
examples/ruby/only_one_blocking.rb
f = File.open($PROGRAM_NAME, 'r')
f.flock(File::LOCK_EX)
puts "Running #{$$}"
sleep 10