20

This is an example of a bash script which checks for some running process (daemon or service) and does specific actions (reload, sends mail) if there is no such process running.

check_process(){
        # check the args
        if [ "$1" = "" ];
        then
                return 0
        fi

        #PROCESS_NUM => get the process number regarding the given thread name
        PROCESS_NUM='ps -ef | grep "$1" | grep -v "grep" | wc -l'
        # for degbuging...
        $PROCESS_NUM
        if [ $PROCESS_NUM -eq 1 ];
        then
                return 1
        else
                return 0
        fi
}

# Check whether the instance of thread exists:
while [ 1 ] ; do
        echo 'begin checking...'
        check_process "python test_demo.py" # the thread name
        CHECK_RET = $?
        if [ $CHECK_RET -eq 0 ]; # none exist
        then
                # do something...
        fi
        sleep 60
done

However, it doesn't work. I got "ERROR: Garbage option." for the ps command. What's wrong with these scripts? Thanks!

4
  • 3
    I'd recommend you using pgrep -f "$1" instead of ps | grep | grep combo. Commented Oct 10, 2011 at 5:07
  • 1
    The code chunk: "if [ $PROCESS_NUM -eq 1]; then return 1; else return 0; fi" is not very idiomatic. It's much cleaner to simply end the function with "test $PROCESS_NUM -ne 1". The return value of the last command will be returned from the function. Commented Oct 10, 2011 at 5:35
  • depending on what your needs are there may be better tools for the job. In particular, if you need to make sure that a process is running, check out the supervise program from daemontools Commented Feb 14, 2012 at 4:27
  • Also see askubuntu.com/a/157900/13975 and especially the explanation linked therein: mywiki.wooledge.org/…... Commented Aug 30, 2016 at 3:44

3 Answers 3

41

You can achieve almost everything in PROCESS_NUM with this one-liner:

[ `pgrep $1` ] && return 1 || return 0

if you're looking for a partial match, i.e. program is named foobar and you want your $1 to be just foo you can add the -f switch to pgrep:

[[ `pgrep -f $1` ]] && return 1 || return 0

Putting it all together your script could be reworked like this:

#!/bin/bash

check_process() {
  echo "$ts: checking $1"
  [ "$1" = "" ]  && return 0
  [ `pgrep -n $1` ] && return 1 || return 0
}

while [ 1 ]; do 
  # timestamp
  ts=`date +%T`

  echo "$ts: begin checking..."
  check_process "dropbox"
  [ $? -eq 0 ] && echo "$ts: not running, restarting..." && `dropbox start -i > /dev/null`
  sleep 5
done

Running it would look like this:

# SHELL #1
22:07:26: begin checking...
22:07:26: checking dropbox
22:07:31: begin checking...
22:07:31: checking dropbox

# SHELL #2
$ dropbox stop
Dropbox daemon stopped.

# SHELL #1
22:07:36: begin checking...
22:07:36: checking dropbox
22:07:36: not running, restarting...
22:07:42: begin checking...
22:07:42: checking dropbox

Hope this helps!

Sign up to request clarification or add additional context in comments.

6 Comments

What if I need to use this to look for a python script? It will work if I look for "python" but not if I look for "myscript.py"
@Pitto - if you have a new question or a different one then please ask it.
If two users give a bash script the same name, will this still work?
@ButtleButkus - depends. If it's 2 different users they cannot see each other's processes in the ps output.
@ButtleButkus - flock to ensure exclusivity.
|
27

If you want to execute that command, you should probably change:

PROCESS_NUM='ps -ef | grep "$1" | grep -v "grep" | wc -l'

to:

PROCESS_NUM=$(ps -ef | grep "$1" | grep -v "grep" | wc -l)

1 Comment

+1, $ ps aux | grep xchat | grep -v "grep" | awk '{print $2}' | xargs echo "ProcessID was:" ProcessID was: 21489
1
PROCESS="process name shown in ps -ef"
START_OR_STOP=1        # 0 = start | 1 = stop

MAX=30
COUNT=0

until [ $COUNT -gt $MAX ] ; do
        echo -ne "."
        PROCESS_NUM=$(ps -ef | grep "$PROCESS" | grep -v `basename $0` | grep -v "grep" | wc -l)
        if [ $PROCESS_NUM -gt 0 ]; then
            #runs
            RET=1
        else
            #stopped
            RET=0
        fi

        if [ $RET -eq $START_OR_STOP ]; then
            sleep 5 #wait...
        else
            if [ $START_OR_STOP -eq 1 ]; then
                    echo -ne " stopped"
            else
                    echo -ne " started"
            fi
            echo
            exit 0
        fi
        let COUNT=COUNT+1
done

if [ $START_OR_STOP -eq 1 ]; then
    echo -ne " !!$PROCESS failed to stop!! "
else
    echo -ne " !!$PROCESS failed to start!! "
fi
echo
exit 1

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.