3

I've written a simple init script to start and stop a Python script as a service. I have to be explicit about the version of Python I'm running, because this is on a CentOS 5 box with Python 2.4 & 2.6 installed (both via yum).

Here's what I have so far:

#!/bin/sh
# chkconfig: 123456 90 10

workdir=/usr/local/bin/Foo

start() {
    cd $workdir
    /usr/bin/python26 $workdir/Bar.py &
    echo "FooBar started."
}

stop() {
    pid=`ps -ef | grep '[p]ython26 /usr/local/bin/Foo/Bar.py' | awk '{ print $2 }'`
    echo $pid
    kill $pid
    sleep 2
    echo "FooBar stopped."
}

case "$1" in
  start)
    start
    ;;
  stop)
    stop
    ;;
  restart)
    stop
    start
    ;;
  *)
    echo "Usage: /etc/init.d/foobar {start|stop|restart}"
    exit 1
esac
exit 0

So:

1) I want to be "smarter" about the filename and directory name management, and set some variables up to so that anything repeated later in the script (like workdir). My main problem is the grep statement, and I haven't figured out how to deal with the variables inside the grep. I'd love any suggestions of a more efficient way to do this.

2) I want to add "status" support to this init script and have it check to see if the Bar.py is running.

  • 1
    Could you clarify what your grep is supposed to be doing? Why are you greping for all that if all you need is the PID of Bar.py? Why not use pgrep? Why is the python version relevant? – terdon Jul 19 '14 at 14:40
  • Great question - and the answer is because I never knew about pgrep! :) – SteveJ Jul 19 '14 at 20:14
3

I may be missing something but I don't understand why you are fiddling with grep in the first place. That's what pgrep is for:

#!/bin/sh
# chkconfig: 123456 90 10

workdir=/usr/local/bin/Foo

start() {
    cd $workdir
    /usr/bin/python26 $workdir/Bar.py &
    echo "FooBar started."
}

stop() {
    pid=`pgrep -f '/Bar.py$'`
    echo $pid
    kill $pid
    sleep 2
    echo "FooBar stopped."
}

case "$1" in
  start)
    start
    ;;
  stop)
    stop
    ;;
  restart)
    stop
    start
    ;;
  *)
    echo "Usage: /etc/init.d/foobar {start|stop|restart}"
    exit 1
esac
exit 0

The pgrep command is designed to return the PIDs of processes whose name matches the pattern given. Since this is a python script, the actual process is something like:

python /usr/local/bin/Bar.py

Where the process name is python. So, we need to use pgrep's -f flag to match the entire name:

   -f, --full
          The pattern is normally only matched against the  process  name.
          When -f is set, the full command line is used.

To ensure that this does not match things like fooBar.py, the pattern is /Bar.py$ so that it matches only the portion after the last / and at the end of the string ($).

For future reference, you should never use ps | grep to get a PID. That will always return at least two lines, one for the running process and one for the grep you just launched:

$ ps -ef | grep 'Bar.py'
terdon   27209  2006 19 17:05 pts/9    00:00:00 python /usr/local/bin/Bar.py
terdon   27254  1377  0 17:05 pts/6    00:00:00 grep --color Bar.py
  • Awesomeness. Didn't know pgrep, so thank you - this works great! – SteveJ Jul 19 '14 at 20:15

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.