Quick bash script for exclusive locks

security-146536_640Sometimes it may be desireable to create a bash script that prevents other scripts from running in parallel wit it.

One way to do this is to use a lock file.

Following is a simple script segment that is useful for managing a lock file:

MAX_LOCK_ATTEMPTS=120
LOCK_WAIT_INTERVAL=5s
LOCK_PATH=$HOME/my.lock

wait_for_lock() {
  for ((i = 0; i < MAX_LOCK_ATTEMPTS; i++)); do
    if (set -o noclobber; > $LOCK_PATH) 2> /dev/null; then
      trap "rm -f '$LOCK_PATH'" EXIT
      return
    fi
    sleep "$LOCK_WAIT_INTERVAL"
  done
  echo "Timed out waiting for lock" >&2
  exit 1
}

The function above tries to lock a lock file that is located in the path specified in the LOCK_PATH variable. Locking with a lock file, as can be seen in line #7, is simply creating the file while setting the bash noclobber option so that it fails if the file is already there. One thing to note here is the parentheses that make the noclobber option influence only the lock writing command by enclosing it inside a sub-shell.

If the lock file is already there (Which means the lock is locked), the function waits the time specified in LOCK_WAIT_INTERVAL and then retries.

The function can retry locking up to MAX_LOCK_ATTEMPTS times. After that, the function will cause the whole script to exit with an error message. Timing out locks is important on production systems to prevent things from getting stuck forever.

The function uses the ‘trap’ command to ensure that the lock will be freed when the script exits.

Locking with a lock file is simple, but for production code, the right precautions should be taken to avoid deadlocks and other failures.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s