5

I have a working Python based program that I want to run as a daemon. Currently I'm doing it in a very hackish manner of starting it in with screen-d -m name session and killing it with pkill -9 -f name.

Eventually I'm doing to have to move this to the better system we use here (thus I'm not willing to modify the program) but in the interim, I'm looking for a cleaner way to do this.

My current thinking is kick it off as a background task from an inti.d script but how do I write the part to bring it back down?

BCS
  • 75,627
  • 68
  • 187
  • 294

6 Answers6

6

On linux there is a start-stop-daemon utility as part of the init.d tools.

It is very flexible and allows different ways for capturing the pid of your server.

There is also a file /etc/init.d/skeleton which can serve as a basis for your own init.d script.

If your target platform is debian based, it makes sense to create a debina package to deploy it as it also helps getting a daemon properly integrated in the rest of the system. And it is not too complicated (if you have done it ten times before ;-)

BCS
  • 75,627
  • 68
  • 187
  • 294
Peter Tillemans
  • 34,983
  • 11
  • 83
  • 114
5

See PEP 3143 -- Standard daemon process library

vartec
  • 131,205
  • 36
  • 218
  • 244
3

If you want to do it with code in python, this is a pretty standard C-method that was ported to python that I use. It works flawlessly, and you can even choose a file output.

import os
import signal
def daemonize(workingdir='.', umask=0,outfile='/dev/null'):
#Put in background
pid = os.fork()
if pid == 0:
    #First child
    os.setsid()
    pid = os.fork() #fork again
    if pid == 0:
        os.chdir(workingdir)
        os.umask(umask)
    else:
        os._exit(0)
else:
    os._exit(0)

#Close all open resources
try:
    os.close(0)
    os.close(1)
    os.close(2)
except:
    raise Exception("Unable to close standard output. Try running with 'nodaemon'")
    os._exit(1)

#Redirect output
os.open(outfile, os.O_RDWR | os.O_CREAT)
os.dup2(0,1)
os.dup2(0,2)

Then, you can use signals to catch when a kill-signal was sent to the program and exit nicely. Example from Python Docs

import signal, os

def handler(signum, frame):
    print 'Signal handler called with signal', signum
    raise IOError("Couldn't open device!")

# Set the signal handler and a 5-second alarm
signal.signal(signal.SIGALRM, handler)
signal.alarm(5)

# This open() may hang indefinitely
fd = os.open('/dev/ttyS0', os.O_RDWR)

signal.alarm(0)          # Disable the alarm
Chris
  • 201
  • 2
  • 4
2

There are modules that could be used to daemonize a python script.

python-daemon implements the well-behaved daemon specification (PEP 3143).

Also this module recently came up on github which seems more pythonic and easy to use.

Sergey R
  • 109
  • 1
  • 1
1

Starting it with an init.d style script is a good way. You take it down with POSIX Signals ... See StackOverflow, Signal handling in Python.

Community
  • 1
  • 1
Aiden Bell
  • 28,212
  • 4
  • 75
  • 119
  • I can `kill -9` it for all I care, but I don't know how to reliably find its PID. – BCS Jun 01 '10 at 17:24
  • @BCS: `-9` is often ... *overkill* (pardon the pun). See [kill -9](http://speculation.org/garrick/kill-9.html). As for finding its PID, your script can create a pidfile in `/var/run` or use a lib that allows you to set `argv[0]` to some easily identified name for use with `pkill`. – Dennis Williamson Jun 01 '10 at 18:17
0

Try this question or more exactly accepted solution.

Community
  • 1
  • 1
Ib33X
  • 6,764
  • 4
  • 28
  • 30
  • I'd really rather not muck with the internals of the program. Heck I'd rather keep what I'm using now rather than do that. – BCS Jun 01 '10 at 18:13
  • Really you don't need to change your program, if it is importable. Joust import your main in deamon-example Run method, (replace while loop). – Ib33X Jun 02 '10 at 11:35