Python Daemon-Prozess

Datum: 22. Februar 2011 17:16:48 — Tags: daemon, Linux, Python,

Dieses Script kann als Grundlage für einen Daemon verwendet werden. Kurz zusammengefasst prüft das Script mittels einer Lock-Datei ob der Daemon bereits läuft und startet ihn dann mittels einer double fork Methode um das Auftreten eines Zombie-Prozesses zu verhindern. Der Daemon-Prozess ist dann direkt ein Kind-Prozess von init und kann somit beim Beenden keinen Ärger mehr machen.

Übrigens ist dieses Script nur für UNIX-Systeme. Bei Windows werden Daemons Dienste genannt und funktionieren ganz anders.

Nähere Beschreibungen befinden sich im Quellcode.

Siehe auch os.fork, os.setsid und os.kill.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
#!/usr/bin/env python

import sys, os, time
import signal
from datetime import datetime

LOCKFILE="daemon.lock"

def daemon():
    """ Dummy fuer die Daemonfunktion. """
    while True:
        f = open("test","w")
        f.write(str(datetime.now()))
        f.close()
        time.sleep(1)

def write_pid( pid ):
    """ Schreibt die PID in die Lockfile. """
    with open(LOCKFILE, "w") as f:
        f.write( str(pid) )

def read_pid():
    """ Liest die PID aus der Lockfile und gibt sie zurueck falls der
        Prozess lauft. Wenn nicht gibt er 0 zurueck. """
    try:
        with open(LOCKFILE) as f:
            try:
                pid = int( f.read() )
            except ValueError:
                raise ValueError("Die Lockfile enthaelt keine PID.")

        if os.path.exists("/proc/{0}".format(pid)):
            return pid
        else:
            return 0
    except IOError:
        return 0 # No such file

def start():
    """ Startet den Daemon, falls er nicht schon laeuft. Der Rueckgabewert
        ist True wenn der Daemon gestartet wurde und False wenn er bereits
        lauft. """

    if read_pid():
        return False

    # Der Prozess muss nun zwei Mal geforkt werden um einen Zombieprozess
    # zu verhindern.

    # Erster fork
    pid = os.fork()
    if pid != 0:
        os._exit(0) # beendet den Elternprozess

    os.setsid() # werde zum Sessionleiter

    # Zweiter fork
    pid = os.fork()
    if pid != 0: # Elternprozess
        write_pid(pid) # nun muss die Prozess ID gespeichert werden
        return True

    else: # Kindprozess
        # Hier wird die Daemonfunktion aufgerufen. Kann auch jede andere
        # Funktion sein. Macht natuerlich nur Sinn, wenn die Funktion in
        # einer Endlosschleife lauft.
        daemon()

        os._exit(0)

def stop():
    """ Stoppt den Daemon. """
    pid = read_pid()

    if not pid:
        return False

    os.kill(pid, signal.SIGTERM)
    return True

if __name__ == '__main__':
    try:
        cmd = sys.argv[1]
    except:
        cmd = None

    if cmd == 'start':
        start()
        sys.exit(0)

    elif cmd == 'stop':
        stop()
        sys.exit(0)

    elif cmd == "restart":
        stop()
        time.sleep(2)
        start()
        sys.exit(0)

    print "USAGE: daemon.py start|stop|restart"

Kommentare

Kommentar senden

» Keine Kommentare vorhanden.

Kommentar senden