0

I'm trying to write a script that will check if a script is already running, and not run it on cron if its still going from the last run. I found another post on here where they suggested using:

echo `pgrep -f $0` . "!=" . "$$";
if [[ `pgrep -f $0` != "$$" ]];

While this seems to work when I run it manually in SSH, it gives weird results when run via cron:

14767 14770 . != . 14770

Is this because there are 2 processes running with 2 different pids?

I have come up with this as an alternative:

if [ -n "$(ps -ef | grep -v grep | grep 'run.sh' | wc -l)" > 2 ];
then
    echo "already running"
else
  # do some stuff here
fi

Running the command on its own seems to work as expected:

# ps -ef | grep -v grep | grep 'run.sh' | wc -l)
2

But when in the code, it always shows "already running" , even though my condition is not met:

bash run.sh
2
already running

Maybe I'm doing something wrong with the variable as an int?

UPDATE: As suggested, I am trying flock:

#!/bin/bash

[ "${FLOCKER}" != "$0" ] && exec env FLOCKER="$0" flock -en "$0" "$0" "$@" || :

#... rest of code here

But I get:

flock: failed to execute run.sh: No such file or directory

1 Answer 1

1

You could write your code like that but it will be complex and errorprone. Better to use file-locking. The flock command exists for this. Its man-page provides various examples you can cut and paste, including:

#!/bin/bash

[ "${FLOCKER}" != "$0" ] && exec env FLOCKER="$0" flock -en "$0" "$0" "$@" || :

# ... rest of code ...

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.

man flock for details.

Sign up to request clarification or add additional context in comments.

6 Comments

Oh now thats cool! I got this though when running: flock: failed to execute run.sh: No such file or directory (updated opening post to show what I have now)
@AndrewNewby you shouldn't be using relative pathnames in cron. Use the full path. Or work out the full path (eg. me=$(realpath "$0")) and use that instead of $0
ahhh ok makes sense. So I changed to me=$(realpath "$0") [ "${FLOCKER}" != "$me" ] && exec env FLOCKER="$me" flock -en "$me" "$me" "$@" || :, but I now get: flock: failed to execute /home/full/path/run.sh: Permission denied. I thought maybe it weas a CHMOD issue on the run.sh script or the dir its in, but that doens't seem to help
Ah ok - so it was a combo of a "chmod" issue (666 wasn't enough), and also the fact it was owned by a user, but I was running as root. All running fine now - thanks !
Very bad idea to run a user-owned script as root! Run it as the user.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.