I have a cron job set up which is set to run every 10 seconds.
What I need to do is have the script do a check to see if it is already running such that if it is running it wont fire up additional instances and processes according to its normal process.
For example if I have a script which checks to see if a file exists, and if exists, does a copy or move function of the file to another location, and then runs another process on it. If it is a large file that takes a long time to copy, and/or the other processes which I run on it takes a long time to complete, I don't want it to automatically fire up another instance of itself every 10 seconds.
So, lets say I have a script like the following: (and this isn't proper code, but just to illustrate the functions)
#!/bin/bash
#
1) Check to see if I am already running, and if so exit.
2) Check to see if file exists, and if it does process it.
EOF
What I am looking for is some way to determine if the script is running as in function 1.
There are a couple of problems here. First, if the script is already running, the trap removes the lock file after reporting that the script is running.
And second, since the test for the lock file and the creation of the lock file is not a single atomic operation, there is a chance that the test by two are more invocations of this script could all succeed without knowing that another script had also succeeded.
The following script moves the trap on EXIT so that it only removes the lock file after this invocation of the script successfully creates the lock file. It also uses set -C to make the test for existence of the lock file and the creation of the lock file a single atomic operation. It also stores the PID of the lock holder in the lock file.
Unlike fpmurphy's script, this script does not remove the lock file if the script is terminated by a common signal. Note that the SIGKILL signal can't be caught and the lock file will never be removed in this case. If the script is terminated by a trapped signal, the exit code will be 128 plus the signal number; and if the script terminated normally, the exit code will be 0. (The script fpmurphy provided always exits with exit code 255 whether or not the script was terminated by a signal or completed successfully.) I did not install a trap on SIGALRM because this script uses sleep for demonstration purposes and some implementations of sleep use the SIGALRM signal. If you choose to catch other signals, you can find the signal number for them in /usr/include/signal.h (or something it #includes); the numbers for the signals used in this sample are supposed to be the same on all implementations that conform to the POSIX standards and the Single UNIX Specifications. If you want to remove the lock file in some or all of the signal catching cases, remove the trap "" EXIT from the trap for the desired signal(s):
#!/bin/ksh
IAm="${0##*/}"
LF="/var/run/$IAm.lock"
set -C
if ! echo $$ > "$LF"
then
printf "%s: Exitting, Already running as pid %s.\n" "$IAm" "$(cat "$LF")" >&2
exit 1
fi
set +C
trap 'rm -f "$LF"' EXIT
trap 'echo "$IAm: Terminated by ABRT signal; $LF not removed." >&2
trap "" EXIT
exit 134' ABRT
trap 'echo "$IAm: Terminated by HUP signal; $LF not removed." >&2
trap "" EXIT
exit 129' HUP
trap 'echo "$IAm: Terminated by INT signal; $LF not removed." >&2
trap "" EXIT
exit 130' INT
trap 'echo "$IAm: Terminated by QUIT signal; $LF not removed." >&2
trap "" EXIT
exit 131' QUIT
trap 'echo "$IAm: Terminated by TERM signal; $LF not removed." >&2
trap "" EXIT
exit 143' TERM
echo 'other processing goes here; echo and sleep for demo'
echo "pid $$ sleeping"
sleep 300