12

I need to prevent a script from being executed multiple times simultaneously and so flock seems right up my street.

What I can't figure out is if I need to manually delete the lock file after the completion of the cron job?

I'm using it like this:

# m h dom mon dow user  command
*/20 *  *  *  *  root /usr/bin/flock -w 0 /var/cron.lock /usr/bin/myscript

This script is also executed on machine startup by upstart (this is where the race condition is).

The file is created ok, but I can't really see how the command knows if the lock is being held by another process. It's empty and monitoring it for changes when the cron job is kicked off produces nothing (using fuser).

If someone can explain how it works I'd be very appreciative!

3
  • 1
    Can you explain the meaning of 0 in your command? /usr/bin/flock -w 0
    – h0lmes221B
    Feb 15, 2020 at 11:48
  • @h0lmes221B -w 0 specifies the timeout in seconds 'flock' will wait before if fails if the file cannot be locked.. in this case, it requests that the file lock should be established without waiting, or fail. Jul 20, 2021 at 10:07
  • I have a script that’s writes a line to one file using flock. If I use wait 1 for example and the lock is not obtained will the bash script continue writing or will it fail. Assume I’m writing thousands of lines in a loop
    – chovy
    Nov 21, 2021 at 22:39

2 Answers 2

15

The lock file you specify as the option to /usr/bin/flock; /var/cron.lock remains locked with the flock(2) system call for the duration of your script /usr/bin/myscript. Once your script completes that lock is again released by /usr/bin/flock.

When the /usr/bin/flock command can't achieve a lock, , i.e. because /var/cron.lock is already locked because your script is still running (or any other error condition), /usr/bin/flock won't execute your script. Your script doesn't need to be modified and does not need to do any checking of the lock, that's all done by /usr/bin/flock.

The lock file itself will be created as an empty file by the /usr/bin/flock command if it does not yet exist, but after it has been created the lock file doesn't change, only an flock(2) will be applied and removed. The file won't be removed after your script completes.

0
0

Is there a reason you can't do something like:

# m h dom mon dow user  command
*/20 *  *  *  *  root (/usr/bin/pgrep myscript || /usr/bin/myscript)

If the process cannot be found in the current process snapshot table, it returns 1 and executes /usr/bin/myscript.

If the process can be found in the current process snapshot table, it returns 0 and stops execution.

2
  • 2
    i don't think that will prevent the race condition. The second process might start after pgrep completes but before the intended first instance starts. I could be completely wrong
    – James
    Jan 14, 2016 at 0:47
  • 2
    @James: You are correct, there is a (narrower) race condition between pgrep reading the process table and starting myscript. If you manage to run this command twice in close succession (within ~ a second on slow/loaded enough system), you still can get two new instances. Worse, if you have multiple processes with "myscript" in name, you can get false positives, and zero new instances. In other words, this just complicates things but isn't an actual fix. (Source: bitten by this previously) Mar 27, 2019 at 15:39

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .