2011-01-16 8 views
67

Hallo,Python-Skript als Linux-Service/Dämon

Ich versuche, einen Python-Skript als Dienst (Daemon) auf (ubuntu) Linux laufen zu lassen.

Im Netz gibt es mehrere Lösungen wie:

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

Ein gut erzogener Unix-Daemon-Prozess heikel ist richtig zu machen, aber die erforderlichen Schritte sind sehr ähnlich für jedes Daemon-Programm. Eine DaemonContext-Instanz enthält das Verhalten und die konfigurierte Prozessumgebung für das Programm. Verwenden Sie die Instanz als Kontextmanager, um einen Daemon-Status einzugeben.

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

jedoch, wie ich speziell meinen Python-Skript integrieren will mit ubuntu meiner Lösung Linux ist eine Kombination mit einem init.d Skript ist

#!/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 

und 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) 

Meine Frage ist jetzt, ob dieser Ansatz richtig ist. Muss ich irgendwelche zusätzlichen Signale verarbeiten? Wird es ein "artiger Unix-Daemon Prozess" sein?

Antwort

84

Angenommen, Ihr Daemon läuft ständig (Ereignisschleife, verdreht, was auch immer), können Sie versuchen, upstart zu verwenden.

Hier ist ein Beispiel Emporkömmling Config für einen hypothetischen 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 

Wenn Sie dies als script.conf zu /etc/init einfach speichern Sie tun eine einmalige

$ sudo initctl reload-configuration 
$ sudo start script 

Sie es stoppen mit stop script. Was der obige Upstart-Conf sagt, ist, diesen Dienst bei Neustarts zu starten und ihn auch neu zu starten, wenn er abstürzt.

Zur Signalverarbeitung - Ihr Prozess sollte natürlich auf SIGTERM reagieren. Standardmäßig sollte dies gehandhabt werden, sofern Sie nicht Ihren eigenen Signal-Handler installiert haben.

+2

Sie haben Recht, Emporkömmling ist heutzutage Standard! Da das obige Skript SIGTERM behandelt, sollte es in Ordnung mit Ihrer Konfigurationsdatei sein :) – tauran

+0

Mein Skript wurde auf "upstart" geändert und es funktioniert wie es sollte ... – tauran

+10

Eine zusätzliche Optimierung, die ich gerade gemacht habe. Wenn Ihr Python-Skript unter einem virtualenv ausgeführt wird, müssen Sie nur den Start ändern, um die ausführbare Python-Datei aus der Umgebung zu verwenden: 'exec /home/user/.env/environ/bin/python/some/dir/script.py' –

8

Rlotons Antwort ist gut. Hier ist eine leichte Verfeinerung, nur weil ich eine Menge Zeit mit Debugging verbracht habe. Und ich muss eine neue Antwort machen, damit ich richtig formatieren kann.

Ein paar andere Punkte, die mich zum Debuggen für immer nahm:

  1. Wenn es fehlschlägt, erste Prüfung /var/log/upstart/.log
  2. Wenn Ihr Skript einen Daemon mit implementiert, was Sie tun Verwenden Sie NICHT die Zeilengruppe 'expect daemon'. Keine 'erwarten' funktioniert. Ich weiß nicht warum. (Wenn jemand weiß warum - bitte posten!)
  3. Überprüfen Sie weiterhin "initctl status script", um sicherzustellen, dass Sie bereit sind (Start/Ausführen).(Und ein erneutes Laden tun, wenn Sie Ihre conf-Datei aktualisieren)

Hier ist meine 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 
+0

Wenn ich diese Konfig kopieren in/etc/init geben Sie dann service myservicename ein, es wird nicht gefunden. Was ist damit. – David

+0

Haben Sie 'initctl reload-configuration' gefolgt von' service myservice start' ausgeführt? –

+0

Entschuldigung, es funktioniert jetzt. Ich tippte Service servicename und dachte, dass es mir meine Optionen anscheinend nicht geben würde .... Sie müssen servicename starten stoppen oder neu starten. Danke für die Antwort trotzdem – David