2011-01-16 20 views
67

Hallo,Python script come servizio Linux/daemon

Sto cercando di lasciare uno script python eseguito come servizio (demone) il (ubuntu) linux.

Sul web esistono diverse soluzioni come:

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

A ben educati processo daemon Unix è difficile da ottenere, ma i passaggi necessari sono più o meno lo stesso per ogni programma demone. Un'istanza DaemonContext contiene il comportamento e l'ambiente di processo configurato per il programma; utilizzare l'istanza come gestore di contesto per immettere uno stato daemon.

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

Tuttavia come voglio per integrare il mio script python in particolare con Ubuntu Linux la mia soluzione è una combinazione con uno script 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 

e in pitone:

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) 

La mia domanda ora è se questo approccio è corretto. Devo gestire eventuali segnali aggiuntivi? Sarà un "processo demone Unix ben educato"?

risposta

84

Supponendo che il tuo demone abbia un modo di funzionare continuamente (qualche ciclo di eventi, contorto, qualunque cosa), puoi provare a usare upstart.

Ecco un esempio di configurazione parvenu per un servizio Python ipotetica:

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 

Se si salva questo come script.conf a /etc/init voi semplice fare una sola volta

$ sudo initctl reload-configuration 
$ sudo start script 

È possibile fermarlo con stop script. Ciò che la conf precedente Upstart dice è di avviare questo servizio al riavvio e anche riavviarlo se muore.

Per quanto riguarda la gestione del segnale, il processo deve rispondere in modo naturale a SIGTERM. Di default questo dovrebbe essere gestito a meno che tu non abbia installato appositamente il tuo gestore di segnale.

+2

È giusto, upstart è lo standard al giorno d'oggi! Poiché lo script precedente gestisce SIGTERM, dovrebbe essere ok con il file di configurazione :) – tauran

+0

Modificato il mio script per il riavvio e funziona come dovrebbe ... – tauran

+10

Un tweak extra che ho appena creato. Se il tuo script python viene eseguito con virtualenv, devi solo cambiare upstart per utilizzare l'eseguibile python dall'ambiente: 'exec /home/user/.env/environment/bin/python/some/dir/script.py' –

8

La risposta di Rloton è buona. Ecco una leggera raffinatezza, solo perché ho passato un lungo periodo di debugging. E ho bisogno di fare una nuova risposta in modo da poter formattare correttamente.

Un paio di altri punti che mi ha portato per sempre per il debug:

  1. Quando non riesce, primo controllo /var/log/upstart/.log
  2. Se lo script implementa un demone con , si fanno NON usare la stanza 'expect daemon'. Non avendo lavori "aspettati". Non so perché. (Se qualcuno sa perché - per favore!)
  3. Inoltre, continua a controllare "script di stato initctl" per assicurarti di essere attivo (avvio/esecuzione).(E fare una ricarica quando si aggiorna il file di configurazione)

Ecco la mia versione:

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

Quando copio questa configurazione in/etc/init quindi digita il servizio myservicename che non lo trova. Cosa succede con quello. – David

+0

Hai fatto 'initctl reload-configuration' seguito da' service myservice start'? –

+0

Ci scusiamo, funziona ora. Stavo digitando il servizio nomeservizio pensando che mi daresti le mie opzioni apparentemente no .... devi fare servicename start stop o restart. Grazie comunque per la risposta – David