Bash: execute a script only when no other instance of the script is running.

Possible issues having two instances of a cronjob at the same time

Bash: execute a script only when no other instance of the script is running.
Photo by Alexander Sinn on Unsplash

If you are a system administrator or a developer is much likely that you had configure a cronjob to run a script, in most of the cases the script exits very fast and never you never fall into the situation to have two instances of the script running. Depending on the script functionality it might or not being a issue to have the same script running, for example it might not cause a functionality issue but the processes that the script execute might cause memory or cpu consumption that would ultimately cause the server to crash or have other instances of the script never to complete.

What to do

Unfortunately cron does not have any built in functionality to limit the number of instances for a cronjob, this means that the sysadmin or the developer has to deal with that, if the script is a shell script just after the /bin/bash line you can enter the following. This cute one-liner will exit to the shell if more than one instance is running.[ "$(pidof -x $(basename $0))" != $$ ] && exit

How this cute one-liner works

  • $$ : Gets the current bash shell PID, $$ in a bash script is the scripts PID
  • $0 : The name of the script
  • basename : prints the last part of a filename
  • pidof -x : Gets the PIDs of $(basename $0) it return many PIDs if the script runs more than once.
  • && exit if the previous statement returns 0 exits

Gluing all this together means that if $$ is not exactly the same as the result of pidof -x $(basename $0) then exit, this means that the current script has more than one instances running.

But what you can do if the script is not a bash script, it can be a python or a binary, or just because of policy you should not edit the script anyway, fortunately Linux is powerful and can help us on this, please welcome the flock command!

How to use flock

flock creates a lock-file somewhere in the filesystem while our program runs, if we try to run another instance of our program with flock while the first instance is still runs the program will not execute.

The generic syntax of flock is/usr/bin/flock -w 0 /tmp/<lockfile> -c '<program-to-execute>'

  • flock : is the flock program
  • -w 0 : The wait parameter defines how much flock will wait for the lock to released, if set to 0 it will exit immediately
  • -c <program-to-execute> : if no lock exists then this program will executed and create a lock with the name of /tmp/<lockfile> as long as it runs

A flock example:

On a shell enter the following/usr/bin/flock -w 0 /tmp/test.lock -c 'echo "sleeping" && sleep 60' || echo "cannot be executed an instance already runs"

This will print sleeping on the screen and will exit after 60 seconds.

if you try to run this in another terminal while it still runs it will printcannot be executed an instance already runs

This happens because the sleep has not completed the execution and and the lock-file exists, then flock exits with a return code not equal to 0 which triggers the command after the ||

if you run this after the 60 seconds sleep, then the sleep command will execute again and will create again the lock-file.

I hope you found this article easy to read and enjoyable :)

Join Medium with my referral link - Konstantinos Patronas
As a Medium member, a portion of your membership fee goes to writers you read, and you get full access to every story…