2011-01-16 21 views
67

Hallo,skrypt Pythona jako usługi Linux/demon

Próbuję pozwolić uruchomić skrypt Pythona jako usługi (demon) na linux (ubuntu).

W sieci istnieje kilka rozwiązań, takich jak:

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

Dobrze ułożona proces demona Unix jest trudne, aby uzyskać prawo, ale wymagane kroki są takie same dla każdego programu demon. Instancja DaemonContext przechowuje zachowanie i skonfigurowane środowisko procesu dla programu; użyj instancji jako menedżera kontekstu, aby wprowadzić stan demona.

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

Jednak jak chcę zintegrować mój skrypt Pythona konkretnie Ubuntu moje rozwiązanie jest połączeniem ze skryptu init.d

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

oraz w Pythonie:

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) 

Moje pytanie brzmi teraz, czy to podejście jest poprawne. Czy muszę obsługiwać dodatkowe sygnały? Czy będzie to "dobrze zachowany proces demona Unixa"?

Odpowiedz

84

Zakładając, że twój demon ma jakiś sposób ciągłego działania (jakaś pętla zdarzeń, skręcony, cokolwiek), możesz spróbować użyć upstart.

Oto przykład dorobkiewicz config dla hipotetycznej usługi Python:

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 

Jeśli zapiszesz to jako script.conf do /etc/init Ci prosty zrobić jednorazową

$ sudo initctl reload-configuration 
$ sudo start script 

Można go zatrzymać z stop script. To, co mówi powyższy konwent, to rozpoczęcie tej usługi po ponownym uruchomieniu komputera, a także ponowne uruchomienie, jeśli umrze.

Jeśli chodzi o obsługę sygnałów - Twój proces powinien naturalnie odpowiadać na SIGTERM. Domyślnie powinno to być obsługiwane, chyba że zainstalowałeś własny program obsługi sygnału.

+2

Państwo rację, dorobkiewicz to standard w dzisiejszych czasach! Ponieważ powyższy skrypt obsługuje SIGTERM, powinno być dobrze z twoim plikiem konfiguracyjnym :) – tauran

+0

Zmieniono mój scenariusz na upstart i działa tak, jak powinien ... – tauran

+10

Jedno dodatkowe usprawnienie, które właśnie zrobiłem. Jeśli twój skrypt Pythona działa pod virtualenv, wystarczy zmienić Upstart, aby użyć pliku wykonywalnego Pythona ze środowiska: 'exec /home/user/.env/environ/bin/python/some/dir/script.py' –

8

Odpowiedź Rlotona jest dobra. Oto lekkie wyrafinowanie, tylko dlatego, że spędziłem mnóstwo czasu na debugowaniu. I muszę zrobić nową odpowiedź, aby móc poprawnie formatować.

kilka innych punktów, które zajęło mi zawsze do debugowania:

  1. Gdy to zawiedzie, należy najpierw sprawdzić /var/log/upstart/.log
  2. Jeśli skrypt implementuje demona z , robisz NIE używaj zwrotki "oczekiwać demona". Brak pracy "oczekuj". Nie wiem dlaczego. (Jeśli ktoś wie dlaczego - proszę pisać!)
  3. Sprawdzaj również "skrypt statusu initctl", aby upewnić się, że jesteś w górze (start/running).(I zrobić reload podczas aktualizacji pliku conf)

Oto moja wersja:

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

Kiedy kopiuję tę konfigurację do/etc/init następnie wpisz service myservicename, ale go nie znajduje. Co z tym. – David

+0

Czy wykonałeś 'initctl reload-configuration', a następnie' service myservice start'? –

+0

Przepraszam za to, że działa teraz. Piszę service servicename myśląc, że dałoby mi moje opcje najwyraźniej nie .... musisz zrobić servencame start stop lub restart. Dzięki za odpowiedź i tak – David

Powiązane problemy