Quick-and-dirty way to ensure only one instance of a shell script is running at a time
Here's an implementation that uses a lockfile and echoes a PID into it. This serves as a protection if the process is killed before removing the pidfile:
LOCKFILE=/tmp/lock.txt
if [ -e ${LOCKFILE} ] && kill -0 `cat ${LOCKFILE}`; then
echo "already running"
exit
fi
# make sure the lockfile is removed when we exit and then claim it
trap "rm -f ${LOCKFILE}; exit" INT TERM EXIT
echo $$ > ${LOCKFILE}
# do stuff
sleep 1000
rm -f ${LOCKFILE}
The trick here is the kill -0
which doesn't deliver any signal but just checks if a process with the given PID exists. Also the call to trap
will ensure that the lockfile is removed even when your process is killed (except kill -9
).
What is the best way to ensure only one instance of a Bash script is running?
If the script is the same across all users, you can use a lockfile
approach. If you acquire the lock, proceed else show a message and exit.
As an example:
[Terminal #1] $ lockfile -r 0 /tmp/the.lock
[Terminal #1] $
[Terminal #2] $ lockfile -r 0 /tmp/the.lock
[Terminal #2] lockfile: Sorry, giving up on "/tmp/the.lock"
[Terminal #1] $ rm -f /tmp/the.lock
[Terminal #1] $
[Terminal #2] $ lockfile -r 0 /tmp/the.lock
[Terminal #2] $
After /tmp/the.lock
has been acquired your script will be the only one with access to execution. When you are done, just remove the lock. In script form this might look like:
#!/bin/bash
lockfile -r 0 /tmp/the.lock || exit 1
# Do stuff here
rm -f /tmp/the.lock
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/pidfile
if [ -f "$pidfile" ] && kill -0 `cat $pidfile` 2>/dev/null; then
echo still running
exit 1
fi
echo $$ > $pidfile
Bash script to ensure only one instance of a script running & others waiting
From man flock:
[ "${FLOCKER}" != "$0" ] && exec env FLOCKER="$0" flock -en "$0" "$0"
"$@" || :This is useful boilerplate code for shell scripts. Put it at
the top of the shell script you want to lock and it'll automatically
lock itself on the first run. If the env var $FLOCKER is not set to
the shell script that is being run, then execute flock and grab an
exclusive non-blocking lock (using the script itself as the lock file)
before re-execing itself with the right arguments. It also sets the
FLOCKER env var to the right value so it doesn't run again.
Put this on top of ./script.sh
(or on top of runner.sh
) and your're good to go.
Continue script if only one instance is running?
Jefromi is correct; here is the logic I think you want:
#!/bin/bash
# this is "test.sh"
if [ $(pidof -x test.sh| wc -w) -gt 2 ]; then
echo "More than 1"
exit
fi
echo "Only one; doing whatever..."
Quick-and-dirty way to ensure only one instance of a shell script is running at a time
Here's an implementation that uses a lockfile and echoes a PID into it. This serves as a protection if the process is killed before removing the pidfile:
LOCKFILE=/tmp/lock.txt
if [ -e ${LOCKFILE} ] && kill -0 `cat ${LOCKFILE}`; then
echo "already running"
exit
fi
# make sure the lockfile is removed when we exit and then claim it
trap "rm -f ${LOCKFILE}; exit" INT TERM EXIT
echo $$ > ${LOCKFILE}
# do stuff
sleep 1000
rm -f ${LOCKFILE}
The trick here is the kill -0
which doesn't deliver any signal but just checks if a process with the given PID exists. Also the call to trap
will ensure that the lockfile is removed even when your process is killed (except kill -9
).
Shell fragment to make sure only one instance a shell script runs at any given time
Put this at the start of the script
SCRIPTNAME=`basename $0`
PIDFILE=/var/run/${SCRIPTNAME}.pid
if [ -f ${PIDFILE} ]; then
#verify if the process is actually still running under this pid
OLDPID=`cat ${PIDFILE}`
RESULT=`ps -ef | grep ${OLDPID} | grep ${SCRIPTNAME}`
if [ -n "${RESULT}" ]; then
echo "Script already running! Exiting"
exit 255
fi
fi
#grab pid of this process and update the pid file with it
PID=`ps -ef | grep ${SCRIPTNAME} | head -n1 | awk ' {print $2;} '`
echo ${PID} > ${PIDFILE}
and at the end
if [ -f ${PIDFILE} ]; then
rm ${PIDFILE}
fi
This first of all checks for the existence of the pid file and exits if it's present. If so then it confirms that a process under this script name with the old pid is running and exits if so. If not then it carries on and updates the script with the new pid file. The bit at the end checks for the existence of the pid file and deletes it, so the script can run next time.
Check permissions on /var/run are OK for your script though, otherwise create the PID file in another directory. Same directory as the script runs in would be fine.
Related Topics
Linux Desktop Shortcut and Icon from Install
Check If All Lines from One File Are Present Somewhere in Another File
Convert Column to Matrix Format Using Awk
Is There a Libc in Kernel Space
Can't Register a Snapshot Repository in Elasticsearch
Why The Size of an Empty Directory in Linux Is 4Kb
How to Simulate Two Consecutive Enter Key Presses for a Command in a Bash Script
Linux: How to Enable Execute in Place (Xip) for Ramfs/Tmpfs
How to Use Gpg Signing Key on a Remote Server
How to Accept Multiple Tcp Connections in Perl
When Using Cpan in Linux Ubuntu Should I Run It Using Sudo/As Root or as My Default User
How to Make Sure Only One Instance of a Bash Script Is Running at a Time
Cloudera Manager Failed to Authenticate: Exhausted Available Authentication Methods
Vagrant Ssh -C and Keeping a Background Process Running After Connection Closed
How to Do a While Loop with a String Redirected into It
Runner Is Not Healthy and Will Be Disabled
Using a Chef Recipe to Append Multiple Lines to a Config File