I'm running a script which is meant to process a few utilities in order to recover some data. This script is situated in a directory where the users can place their file that needs to be recovered. Since many users can have access to this directory and run the script, I want to have a condition that checks if the script is already running. If yes, then echo a "try again later" message; otherwise, run as usual.

I did some research on here and figured this to be a working code for my functionality as described above.

me="$(basename "$0")";
running=$(ps h -C "$me" | grep -wv $$ | wc -l);
[[ $running > 1 ]] && exit;

I would like to implement this functionality and the code above in a Solaris SunOS 5.8. I understand that ps functions differently in Unix and Linux.

  • A sure shot way would be to create lock file at the beginning of the script and delete it at the end. When the script is invoked and the lock file is present, it means that the script is still running. This will also take care of cases where the script might be invoked from multiple machines. – amisax May 8 '18 at 9:12
  • If you're decide to use a lock file mechanism as @amisax describes, you need to add trap handlers to your script to clean up the lock file if a user kills a running instance with CTRL-C or similar. And you'll also likely have to deal with cleaning up after users either kill -9 ... a running script or remove the lock file themselves and try running another instance of the script. – Andrew Henle May 8 '18 at 9:48
  • I implemented according to what amisax has suggested, works and is the easiest approach I believe. Thanks! I will indeed add trap handlers. Thanks for your comment, not something I would have thought of on my own @Andrew – ratcat May 9 '18 at 7:03

The ps command you are using is not related to UNIX.

Using key letters instead of options was used in BSD ps but that did never make it into the standard. BSD even uses the h key letter in a different way as you might expect.

I recommend to use:

ps -p $$

If you like to check whether there are more instances of this script, use:

myname=`basename $0`
pids=`pgrep -d, $myname`
ps -p $pids

In theory, you do not even need to run ps anymore, it would be sufficient to check the output of pgrep for a comma.

If you like to implement a lock file algorithm and have a POSIX compliant shell, you may use:

set -o noclobber
:> /var/tmp/myscript
if [ $? -ne 0 ]; then
     echo already running
     exit 1
... do some stuff
rm /var/tmp/myscript

Whether this works reliably depends on whether the shell implements noclobber the way POSIX likes to see it. Some shells may not implement this atomically, so you need to know whether your shell is OK.

  • 3
    Saying to use ps -p $$ means to see if the current process (pid) is still running. It's my interpretation that the OP wants to see if a separate copy of the same script is running. – Jeff Schaller May 8 '18 at 10:04
  • Indeed my intention is as mentioned by Jeff. I want to check if the script is being run by some other user remotely elsewhere to avoid overwriting of data. – ratcat May 9 '18 at 0:55
  • So my updated answer should be sufficient for you... – schily May 9 '18 at 10:27
  • pgrep exits with a non-zero exit status if nothing can be found, just like grep. Some systems implement pgrep with a -q option that works just like with grep too (but not Linux AFAIK). No need to look for a comma. – Kusalananda Nov 15 '19 at 16:25
  • The comma is needed is you like to list all processes using the ps command. This is mentioned in my answer. – schily Nov 15 '19 at 16:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.