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

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .