Until now I used

pidof -o %PPID -x "my-tool"

To detect the pid of an eventually running instance of my-tool.

This is the short version of my-tool file, an executable bash script


if pidof -o %PPID -x "my-tool"; then
   echo "Already running"
   exit 1

 ... if not running go on 

But now I need to allow a single instance per user and multiple per machine, so we can have even 100 my-tool running in the same moment, but only 1 per user.

Note that I need a test to create something like a singleton. If the tool will be started and there is another instance running it will close itself.

In short: I need that a bash script could detect if itself is already running for the current user and in this case it must exit.

How to ?

  • You shouldn't use pidof, there are better tools lie pgrep
    – cat
    Jul 26, 2016 at 22:53

4 Answers 4


Use pgrep instead:

pgrep -cxu $USER -f my-tool

The options used are:

   -c, --count
          Suppress  normal  output; instead print a count of matching pro‐
          cesses.  When count does not match anything, e.g. returns  zero,
          the command will return non-zero value.
   -x, --exact
          Only match processes whose names (or command line if -f is spec‐
          ified) exactly match the pattern.
   -u, --euid euid,...
          Only match processes whose effective user ID is listed.   Either
          the numerical or symbolical value may be used.

If you want to use this in a bash script that checks if it is already running, you could use $0. This expands to the path of the current script (e.g. /home/username/bin/foo.sh) but we only need foo.sh. To get that, we can remove everything up to the last / using bash's string manipulation tools: ${0##*/}. This means we can do something like:

## If there are more than 1 instances of the current script run
## by this user
if [[ $(pgrep -cxu "$USER" "${0##*/}") -gt 1 ]];
        echo "Script already running, exiting."

You might also want to consider using lockfiles for this:

## If the lock file exists
if [ -e /tmp/$USER.foo.lock ]; then
    ## Check if the PID in the lockfile is a running instance
    ## of foo.sh to guard against crashed scripts
    if ps $(cat /tmp/$USER.foo.lock) | grep foo.sh >/dev/null; then
        echo "Script foo.sh is already running, exiting"
        echo "Lockfile contains a stale PID, continuing"
        rm /tmp/$USER.foo.lock 
## Create the lockfile by printing the script's PID into it
echo $$ > /tmp/$USER.foo.lock

## Rest of the script here

## At the end, delete the lockfile
rm /tmp/$USER.foo.lock
  • Let us continue this discussion in chat.
    – terdon
    Jul 26, 2016 at 12:34
  • 1
    Rather than touch /tmp/$USER.foo.lock I would use the PID of the process echo $$ >/tmp/$USER.foo.lock Then logic could be included to test whether such a process actually exists. Jul 26, 2016 at 18:33
  • @MontyHarder indeed, very good suggestion. Answer edited, thanks.
    – terdon
    Jul 27, 2016 at 8:42
  • @terdon, had problem with mobile, deleted that comment in the next second. I meant $(< pidfile) instead of $(cat pidfile) .
    – user311189
    Jul 27, 2016 at 9:15

You can use pgrep fo find if a process is being executed by a specific user and then start the process if not running already by the user:

if pgrep -u "$USER" my-tool &>/dev/null; then
    echo 'You already have my-tool running'

The environment variable, $USER, will be expanded to the currently logged in user i.e. the user running the script. As we are only interested in whether the my-tool is running or not, so just using the exit status directly with if construct is enough.

Use this script as a wrapper for starting my-tool and make the users use this only or rename it as my-tool and rename the original my-tool to something else (and change the name inside the script too).

  • I cannot make a wrapper, long history, ... how can I exclude the current process PID ?
    – realtebo
    Jul 26, 2016 at 12:26
  • @realtebo ummm..exclude PID meaning?
    – heemayl
    Jul 26, 2016 at 12:53

Try it with this snippet:

MyProcessName=$(ps -p $$ -o args=)
AllPids=$(pgrep -fu "$(whoami)" "$MyProcessName")
AllPids=$(tr "\n" ' ' <<<"$AllPids")
Pids=$(sed "s/$Mypid//" <<<"$AllPids")
echo "$$: Instances including itself: $AllPids"
echo "$$: Instances different from itself: $Pids"

It is important to not write pgrep|tr because this would fork into a same named shell.


Wrap the command you wish to run in a flock to ensure that only one copy runs at a time. Use a lock_file stored within a user's home directory tree so that each user has their own lock file. For example:

lockfile = "~/lockfile"
 if flock -n 200; then
    echo "Could not get lock $lock_file
) 200>$lock_file

'command' can be any bash command or script.

man flock gives examples of usage

  • Really, I didn't know flock command at all
    – realtebo
    Aug 9, 2016 at 12:19

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.