How to make sure only one instance of a Bash script is running at a time?
You want a pid file, maybe something like this:
pidfile=/path/to/pidfileif [ -f "$pidfile" ] && kill -0 `cat $pidfile` 2>/dev/null; then echo still running exit 1fi echo $$ > $pidfile
I think you need to use lockfile command. See using lockfiles in shell scripts (BASH) or http://www.davidpashley.com/articles/writing-robust-shell-scripts.html.
The second article uses "hand-made lock file" and shows how to catch script termination & releasing the lock; although using lockfile -l <timeout seconds>
will probably be a good enough alternative for most cases.
Example of usage without timeout:
lockfile script.lock<do some stuff>rm -f script.lock
Will ensure that any second script started during this one will wait indefinitely for the file to be removed before proceeding.
If we know that the script should not run more than X seconds, and the script.lock
is still there, that probably means previous instance of the script was killed before it removed script.lock
. In that case we can tell lockfile
to force re-create the lock after a timeout (X = 10 below):
lockfile -l 10 /tmp/mylockfile<do some stuff>rm -f /tmp/mylockfile
Since lockfile
can create multiple lock files, there is a parameter to guide it how long it should wait before retrying to acquire the next file it needs (-<sleep before retry, seconds>
and -r <number of retries>
). There is also a parameter -s <suspend seconds>
for wait time when the lock has been removed by force (which kind of complements the timeout used to wait before force-breaking the lock).
You can use the run-one
package, which provides run-one
, run-this-one
and keep-one-running
.
The package: https://launchpad.net/ubuntu/+source/run-one
The blog introducing it: http://blog.dustinkirkland.com/2011/02/introducing-run-one-and-run-this-one.html