Single Instance Script on NAS4Free

Great thing about NAS4Free is the opportunity to do really powerful scripting. You can do automation scripts on par with full-blown *nix distributions. Better still, you can even configure them to run at desired times giving you full hand-off experience.

With all that power and possibility of scripts running left and right, it pays off to do some sanity checking. Most common one is disabling multiple instances (particularly important for backup script).

Since NAS4Free is FreeBSD-based, some things might be a bit different than your everyday Linux but rough code would be:

SCRIPT_NAME=`basename $0`
PID_FILE="/var/tmp/.$SCRIPT_NAME.pid"
PID_LAST=`cat $PID_FILE 2> /dev/null`
if [ -n "$PID_LAST" ]; then
    PID_ACTIVE=`ps $PID_LAST | grep "^$PID_LAST" | grep "${SCRIPT_NAME}\$"`
    if [ -n "$PID_ACTIVE" ]; then
        echo "ERROR: Script is already running!" >&2
        exit 255
    fi
fi
echo $$ > $PID_FILE


# DO SOMETHING USEFUL


rm $PID_FILE

When script is started for first time, process identifier (PID) is written to /var/tmp/.script.sh.pid (where script.sh is name of our script). This is followed by some useful action (insert your code here). When the job is done, /var/tmp/.script.sh.pid is simply removed and everything is fresh for a new start.

If we start second instance of script before first one has completed, script will find its temporary file. While it might stop with an error at this point, I prefer it to run additional check. Previous script might have crashed and thus temporary file might be just a leftover and there is nothing really running.

So it reads content of a temporary file in order to find previously used PID. That PID is then found in the list of processes and compared against a script name (maybe some other script is running under same PID - rare but happens). If process with same number and name is found, script throws an error and exits.

Simple and works 99% of time.

Script does have some issues. You cannot have two scripts with same name using the same trick because temporary file is based on a name only. Similar problem might be a false positive if another script with same name accidentally gets same PID as our previously running script (although this is highly unlikely). Solution for both would be using realpath command and basing temporary file and PID search on it.

Another issue might be how easy is to trick script into a parallel execution. Just remove temporary PID file and script will be no wiser. And there is no real way around this. Intention of this code is to prevent accidental parallel execution - if user wants to shoot at his foot, he will do it.

You can really make this as complicated or as simple as you wish. I found my sweet spot in the code above.

[2018-07-22: NAS4Free has been renamed to XigmaNAS as of July 2018]