Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python script as linux service/daemon

Hallo,

I'm trying to let a python script run as service (daemon) on (ubuntu) linux.

On the web there exist several solutions like:

http://pypi.python.org/pypi/python-daemon/

A well-behaved Unix daemon process is tricky to get right, but the required steps are much the same for every daemon program. A DaemonContext instance holds the behaviour and configured process environment for the program; use the instance as a context manager to enter a daemon state.

http://www.jejik.com/articles/2007/02/a_simple_unix_linux_daemon_in_python/

However as I want to integrate my python script specifically with ubuntu linux my solution is a combination with an init.d script

#!/bin/bash  WORK_DIR="/var/lib/foo" DAEMON="/usr/bin/python" ARGS="/opt/foo/linux_service.py" PIDFILE="/var/run/foo.pid" USER="foo"  case "$1" in   start)     echo "Starting server"     mkdir -p "$WORK_DIR"     /sbin/start-stop-daemon --start --pidfile $PIDFILE \         --user $USER --group $USER \         -b --make-pidfile \         --chuid $USER \         --exec $DAEMON $ARGS     ;;   stop)     echo "Stopping server"     /sbin/start-stop-daemon --stop --pidfile $PIDFILE --verbose     ;;   *)     echo "Usage: /etc/init.d/$USER {start|stop}"     exit 1     ;; esac  exit 0 

and in python:

import signal import time import multiprocessing  stop_event = multiprocessing.Event()  def stop(signum, frame):     stop_event.set()  signal.signal(signal.SIGTERM, stop)  if __name__ == '__main__':     while not stop_event.is_set():         time.sleep(3) 

My question now is if this approach is correct. Do I have to handle any additional signals? Will it be a "well-behaved Unix daemon process"?

like image 850
tauran Avatar asked Jan 16 '11 13:01

tauran


People also ask

How do I run a Python script in the background Linux?

To run Python scripts as a background process on Linux or Mac, we use the & operator at the end of the command, which will make it run as a background process.


2 Answers

Assuming your daemon has some way of continually running (some event loop, twisted, whatever), you can try to use upstart.

Here's an example upstart config for a hypothetical Python service:

description "My service" author  "Some Dude <[email protected]>"  start on runlevel [234] stop on runlevel [0156]  chdir /some/dir exec /some/dir/script.py respawn 

If you save this as script.conf to /etc/init you simple do a one-time

$ sudo initctl reload-configuration $ sudo start script 

You can stop it with stop script. What the above upstart conf says is to start this service on reboots and also restart it if it dies.

As for signal handling - your process should naturally respond to SIGTERM. By default this should be handled unless you've specifically installed your own signal handler.

like image 140
rlotun Avatar answered Oct 07 '22 18:10

rlotun


Rloton's answer is good. Here is a light refinement, just because I spent a ton of time debugging. And I need to do a new answer so I can format properly.

A couple other points that took me forever to debug:

  1. When it fails, first check /var/log/upstart/.log
  2. If your script implements a daemon with python-daemon, you do NOT use the 'expect daemon' stanza. Having no 'expect' works. I don't know why. (If anyone knows why - please post!)
  3. Also, keep checking "initctl status script" to make sure you are up (start/running). (and do a reload when you update your conf file)

Here is my version:

description "My service" author  "Some Dude <[email protected]>"  env PYTHON_HOME=/<pathtovirtualenv> env PATH=$PYTHON_HOME:$PATH  start on runlevel [2345] stop on runlevel [016]  chdir <directory>  # NO expect stanza if your script uses python-daemon exec $PYTHON_HOME/bin/python script.py  # Only turn on respawn after you've debugged getting it to start and stop properly respawn 
like image 41
Ross R Avatar answered Oct 07 '22 17:10

Ross R