Find the answer to your Linux question:
Results 1 to 4 of 4
I have a script that I do not run if it is already running. So I put in a check to make sure it is not running already by grepping ...
Enjoy an ad free experience by logging in. Not a member yet? Register.
  1. #1
    Just Joined!
    Join Date
    Jun 2012
    Posts
    11

    script grepping for itself returns additional value


    I have a script that I do not run if it is already running. So I put in a check to make sure it is not running already by grepping the processes to make sure someone else is not running the script already. The problem is, within the script it reports as 2 processes are running instead of just the 1 even though I have another terminal open while it is running to show that there is really only one process.

    This was fine because I simply said if the process count is higher than 2, then close out. However, now we use this script across several machines and when I do my check, since it is looking for the process on a different machine, if it is running over there, it returns 1 as I would expect. This means I have to redo my logic in my script to account for 2 processes on the system I am currently running the script on and 1 process for any other system.

    I am trying to figure out why it does this. I am assuming it has something to do with a script creating its own instance of the shell, but I am not entirely sure what is going on so I was hoping someone could educate me.

    This is the basics of the part of the script I am referring to:
    Code:
    me=`hostname`
    for I in ${array[@]}
    do
    * * if ["$I" == "$me" ] ; then
    * * * * isRunning=`ps -elf | grep script.sh | grep -v grep | grep -v vi | wc -l`
    * * else
    * * * * isRunning=`ssh -x user@"$I" 'ps -elf | grep script.sh | grep -v grep | grep -v vi | wc -l'`
    * * fi
    * * if [ $isRunning -gt 2 \ ; then
    * * * * echo script.sh is already running on $I... Cannot run more than one instance of this script at a time."
    * * * * exit
    * * fi
    done

    so basically, I just realized today that it doesn't do the same 2 count when I ssh to another machine with it running since it is on another machine so I have to duplicate that "if isRunning" statement and put it within the first if/else statements so I can do one for the local machine with 2 and one for a remote machine with 1.

    I am willing to take criticisms and advice on my code as well. I am always looking for ways to improve.

    thanks,

    Jeremy
    Last edited by jedlickaj; 10-02-2012 at 02:55 PM.

  2. #2
    Trusted Penguin
    Join Date
    May 2011
    Posts
    4,353
    Hi,

    Yeah, it can get messy using ps and grep sometimes. I find that pidof usually does a cleaner job.

    Here is an example:

    Code:
    #!/bin/bash
    me=`hostname`
    
    # name of the script
    script='script.sh'
    
    # maximum number of instances of script allowed, per host
    max=1
    
    # list of hosts
    declare -a array
    array=($me 'server1' 'server2')
    
    # list that will hold number of pids per host
    declare -a pids
    
    # loop thru all hosts
    for I in ${array[@]}; do
    
      # empty the list of pids for this host
      pids=()
    
      # run the command
      if [ "$I" == "$me" ]; then
        pids=($(pidof -x $script))
      else
        pids=($(ssh $I pidof -x $script))
      fi
      printf "\nHost $I, number running: '${#pids[*]}'\n"
    
      # see if max number of pids has been reached
      if [ ${#pids[*]} -gt $max ]; then
        echo "The number of running instances of \`$script' in $I has been exceeded"
      fi
    done
    What I am not clear about is how many instances of script you want running. You can modify the max= variable at the top to experiment. If it is one per host, or one total, across all hosts? I coded it to work as the former, but it would be easy to change to the latter (or to other variations, for that matter).

    Regarding the use of pidof, note that sometimes you have to specify the full path, as sometimes it is located in /sbin and you are running it as a non-root user, e.g.:

    Code:
    /sbin/pidof -x script.sh

  3. #3
    Just Joined!
    Join Date
    Jun 2012
    Posts
    11
    thanks.

    So the situation is, it is a test machine. We load software and then under our "test" user, we have our own scripts we use to do installs, setup data, and run automate tests. So this script in particular is a script we use to clean up all the data and reset the system back to the initial install so we can start fresh tests. The script is designed to hit all the servers part of this test system and is designed to be able to be launched from any of the machines and still be able to clean all the systems. So if it is running on one, it stops and starts processes, makes changes to a shared database, and a few other things where if more than one was running and going through each of the systems trying to clean them, it would cause some complications. Since we have several people that work on the system and don't necessarily sit next to each other, we just want to make sure there are not two people that try to run the script at the same time from any of the systems.

    Thanks for posting the pidof stuff. I have always stuck to the traditional ps | grep which is not always the best solution, especially if you are not specific enough on your grep for a process. I have a couple other scripts that start, stop , and check's a series of processes we have. The pidof approach is something I will definitely look into.

    thanks,

    Jeremy

  4. #4
    Trusted Penguin
    Join Date
    May 2011
    Posts
    4,353
    Quote Originally Posted by jedlickaj View Post
    So the situation is, it is a test machine. We load software and then under our "test" user, we have our own scripts we use to do installs, setup data, and run automate tests. So this script in particular is a script we use to clean up all the data and reset the system back to the initial install so we can start fresh tests. The script is designed to hit all the servers part of this test system and is designed to be able to be launched from any of the machines and still be able to clean all the systems. So if it is running on one, it stops and starts processes, makes changes to a shared database, and a few other things where if more than one was running and going through each of the systems trying to clean them, it would cause some complications. Since we have several people that work on the system and don't necessarily sit next to each other, we just want to make sure there are not two people that try to run the script at the same time from any of the systems.
    Then it sounds to me like you definitely want to use max=1 and exit (assuming that this code and everything else is all in one script) if any host finds a pid.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •