wake-up-neo.com

Python Skript als Linux Service / Daemon

Hallo,

Ich versuche, ein python script als service (daemon) unter (ubuntu) linux laufen zu lassen.

Im Web gibt es verschiedene Lösungen wie:

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

Ein ordentlicher Unix-Daemon-Prozess ist schwierig, aber die erforderlichen Schritte sind für jedes Daemon-Programm gleich. Eine DaemonContext-Instanz enthält das Verhalten und die konfigurierte Prozessumgebung für das Programm. Verwenden Sie die Instanz als Kontextmanager, um einen Dämonstatus einzugeben.

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

Da ich mein python -Skript jedoch speziell in Ubuntu Linux integrieren möchte, ist meine Lösung eine Kombination mit einem init.d-Skript

#!/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 __== '__main__':
    while not stop_event.is_set():
        time.sleep(3)

Meine Frage ist nun, ob dieser Ansatz richtig ist. Muss ich mit zusätzlichen Signalen umgehen? Wird es ein "anständiger Unix-Daemon-Prozess" sein?

67
tauran

Angenommen, Ihr Daemon hat eine Art von kontinuierlicher Ausführung (irgendeine Ereignisschleife, verdreht, was auch immer), können Sie versuchen, upstart zu verwenden.

Hier ist ein Beispiel für eine Upstart-Konfiguration 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 unter /etc/init Speichern, führen Sie einfach einen einmaligen Vorgang durch

$ Sudo initctl reload-configuration
$ Sudo start script

Sie können es mit stop script Stoppen. Die obige Konfig für den Neustart besagt, dass dieser Dienst beim Neustart gestartet und auch neu gestartet werden soll, wenn er abstirbt.

Was die Signalverarbeitung betrifft, sollte Ihr Prozess natürlich auf SIGTERM reagieren. Standardmäßig sollte dies behandelt werden, es sei denn, Sie haben speziell Ihren eigenen Signalhandler installiert.

87
rlotun

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

Ein paar andere Punkte, die ich für immer zum Debuggen brauchte:

  1. Wenn dies fehlschlägt, überprüfen Sie zuerst /var/log/upstart/.log
  2. Wenn Ihr Skript einen Daemon mit python-daemon implementiert, verwenden Sie NICHT die Zeilengruppe 'expect daemon'. Keine "Erwartung" zu haben, funktioniert. Ich weiß nicht warum. (Wenn jemand weiß warum - bitte posten!)
  3. Überprüfen Sie auch weiterhin "initctl status script", um sicherzustellen, dass Sie aktiv sind (start/running). (Und lade es neu, wenn du deine conf-Datei aktualisierst.)

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
9
Ross R