Basically, we are counting on the fact that directory creation is atomic, so that only one copy of this script running concurrently can successfully create $LOCKDIR. It's probably best to make sure that $LOCKDIR is on a local drive, not on an NFS disk or a Samba mount, etc.
Just have your script touch a file when it starts and delete that file when it completes. Then within the script, you can check for the existence of that file before doing anything.
In pseudocode:
if (!exists(/var/run/filename))
{
touch /var/run/filename;
do stuff;
rm /var/run/filename;
}
You can do the above where you create a lock file or directory. I personally open a socket connection to some high port. This ensures that even if the application crashes the socket will be closed. With a lock file the file can continue and your script will not run till you manually remove it.
In my experience this has proven to be more reliable.
There is a "lockfile" binary installed on most systems that you can use to avoid getting into the game of bash scripting oneupsmanship. On RHEL/CentOS/Fedora its part of the procmail package.
So you could put something like:
lockfile /var/lock/mycron.lock && /usr/local/bin/mycron && rm -f /var/lock/mycron.lock
There's more options in the man page, you can set it to wait some amount of time, to clean up after itself, etc.
I seem to succeed with to following calling script:
#!/bin/zsh
RED_="\033[31m"
BLUE_="\033[34m"
BLACK_="\033[0m"
if [ $# -lt 1 ]; then
echo "$0: Invoke a program/script only once at a time"
echo "Syntax: $0 <program/script with parameters>"
else
if ps -Alf | grep "$*" | grep -v grep | grep -v $0 >/dev/null; then
echo "$BLUE_\"$@\"$RED_ runs already. I don't invoke it.$BLACK_"
else
echo "${RED_}I invoke: $BLUE_$@$BLACK_"
$@
fi
fi
My apologies to embobo, but I copied his script and modified it to eliminate the race condition that I noted in my comment to his answer:
Basically, we are counting on the fact that directory creation is atomic, so that only one copy of this script running concurrently can successfully create
$LOCKDIR
. It's probably best to make sure that$LOCKDIR
is on a local drive, not on an NFS disk or a Samba mount, etc.You could use a lock file. Example shell code:
It is important to make sure that the lock file gets removed at any kind of exit (normal or abnormal). That is what the
trap
command does.You could make it more sophisticated by doing more if the lock file exists. For example, get the pid from the file and see if it is actually running.
Just have your script touch a file when it starts and delete that file when it completes. Then within the script, you can check for the existence of that file before doing anything.
In pseudocode:
You can do the above where you create a lock file or directory. I personally open a socket connection to some high port. This ensures that even if the application crashes the socket will be closed. With a lock file the file can continue and your script will not run till you manually remove it.
In my experience this has proven to be more reliable.
There is a "lockfile" binary installed on most systems that you can use to avoid getting into the game of bash scripting oneupsmanship. On RHEL/CentOS/Fedora its part of the procmail package.
So you could put something like:
lockfile /var/lock/mycron.lock && /usr/local/bin/mycron && rm -f /var/lock/mycron.lock
There's more options in the man page, you can set it to wait some amount of time, to clean up after itself, etc.
I seem to succeed with to following calling script: