Linux: Single Instance of Shell Script

Objective: Ensure that only a single instance of a shell script is running at a time on Linux.

To allow only a single instance of a shell script to run at a given time, we will need to use file locking. File locking is a mechanism that restricts access to a computer file by allowing only one user or process access at any specific time. Many file lock implementations do not work well as they do not cater for race conditions. Let’s take a look at a few examples.

A typical example of using simple file locks in shell scripts is shown below.

The above code will look for a lock file and if it does not exist, it will create a lock file and assumes it has exclusive rights to the file. But there is a race condition involved as the commands are not atomic in nature. There is a time window between checking and creating the file, during which other programs may act. If two processes run the same code at the same time, both processes will determine that the lock file does not exist and both processes will assume that they have acquired the lock.

Also, if a script has acquired the lock and if the process gets killed using signal 9 (SIGKILL), we may get hit with a stale lock problem – the lock file will not be removed and other processes will have the false impression that the lock is still being held by another process.

On Linux, we can mitigate this problem using flock. Note that flock is not standardised by POSIX and it may/will not work well on NFS filesystems.

The above syntax will create a lock file using FD (file descriptor) 9 and tries to acquire a lock to the file in a non-blocking manner. If the lock is not acquired, flock will return an exit status of 1. In this case, the noflock function is executed – display an error and exit. If the lock is acquired, flock will return 0.

The lock is removed when the shell script has finished executing. However, it may be required in special cases, for example if the enclosed command group may have forked a background process which should not be holding the lock. In this case, you will have to manually remove the lock on the file using the following syntax.

ibrahim = { interested_in(unix, linux, android, open_source, reverse_engineering); coding(c, shell, php, python, java, javascript, nodejs, react); plays_on(xbox, ps4); linux_desktop_user(true); }