I have a script that runs every 15 minutes but sometimes if the box is busy it hangs and the next process will start before the first one is finished creating a snowball effect. How can I add a couple lines to the bash script to check to see if something is running first before starting?
-
See [http://stackoverflow.com/questions/185451/quick-and-dirty-way-to-ensure-only-one-instance-of-a-shell-script-is-running-at-a](http://stackoverflow.com/questions/185451/quick-and-dirty-way-to-ensure-only-one-instance-of-a-shell-script-is-running-at-a). – Rob May 29 '09 at 17:11
-
possible duplicate of [shell script execution check if it is already running or not](http://stackoverflow.com/questions/16807876/shell-script-execution-check-if-it-is-already-running-or-not) – AncientSwordRage May 14 '15 at 10:04
9 Answers
You can use pidof -x
if you know the process name, or kill -0
if you know the PID.
Example:
if pidof -x vim > /dev/null
then
echo "Vim already running"
exit 1
fi
-
1Make sure to use the -x flag if you are checking a script, or you won't get a match, because it will be looking for 'bash' – Nathan Apr 22 '10 at 04:00
Why don't set a lock file ?
Something like
yourapp.lock
Just remove it when you process is finished, and check for it before to launch it.
It could be done using
if [ -f yourapp.lock ]; then
echo "The process is already launched, please wait..."
fi

- 47,316
- 8
- 52
- 87
-
1Because correctly managing a lock file, in particular handling the case where a process exited improperly and failed to clear its lock file, takes more than a couple lines in bash. – chaos May 29 '09 at 17:09
-
1If using `flock`, lock files are easy to manage -- but yes, using `-f` to test their existence is Evil And Wrong. – Charles Duffy Oct 04 '09 at 14:28
This is how I do it in one of my cron jobs
lockfile=~/myproc.lock
minutes=60
if [ -f "$lockfile" ]
then
filestr=`find $lockfile -mmin +$minutes -print`
if [ "$filestr" = "" ]; then
echo "Lockfile is not older than $minutes minutes! Another $0 running. Exiting ..."
exit 1
else
echo "Lockfile is older than $minutes minutes, ignoring it!"
rm $lockfile
fi
fi
echo "Creating lockfile $lockfile"
touch $lockfile
and delete the lock file at the end of the script
echo "Removing lock $lockfile ..."
rm $lockfile

- 75
- 1
- 6
In lieu of pidfiles, as long as your script has a uniquely identifiable name you can do something like this:
#!/bin/bash
COMMAND=$0
# exit if I am already running
RUNNING=`ps --no-headers -C${COMMAND} | wc -l`
if [ ${RUNNING} -gt 1 ]; then
echo "Previous ${COMMAND} is still running."
exit 1
fi
... rest of script ...

- 376
- 1
- 4
-
3I did this and I had to tweak it a little. First, COMMAND includes the full path so unless you run it from the same dir it doesn't work. I hard-coded the name anyway. Second, for some reason ps --no-headers -C${COMMAND} | wc -l always returned 1 with nothing running and since this script is running while it's checking that's another 1 so it always returned 2. I had to change the -gt 1 to -gt 2 and it worked. Thanks. – Ryan Detzel Jun 18 '09 at 16:55
I had recently the same question and found from above that kill -0 is best for my case:
echo "Starting process..."
run-process > $OUTPUT &
pid=$!
echo "Process started pid=$pid"
while true; do
kill -0 $pid 2> /dev/null || { echo "Process exit detected"; break; }
sleep 1
done
echo "Done."

- 1,076
- 10
- 10
For a method that does not suffer from parsing bugs and race conditions, check out:

- 120,288
- 16
- 68
- 77
To expand on what @bgy says, the safe atomic way to create a lock file if it doesn't exist yet, and fail if it doesn't, is to create a temp file, then hard link it to the standard lock file. This protects against another process creating the file in between you testing for it and you creating it.
Here is the lock file code from my hourly backup script:
echo $$ > /tmp/lock.$$
if ! ln /tmp/lock.$$ /tmp/lock ; then
echo "previous backup in process"
rm /tmp/lock.$$
exit
fi
Don't forget to delete both the lock file and the temp file when you're done, even if you exit early through an error.

- 179,021
- 58
- 319
- 408
Use this script:
FILE="/tmp/my_file"
if [ -f "$FILE" ]; then
echo "Still running"
exit
fi
trap EXIT "rm -f $FILE"
touch $FILE
...script here...
This script will create a file and remove it on exit.

- 7,473
- 4
- 24
- 38