Domanda

La ricerca su Google rivela snippet di codice x2. Il primo risultato è questa ricetta di codice che ha molta documentazione e spiegazione, insieme ad alcuni discussione utile sotto.

Tuttavia, un altro esempio di codice , sebbene non contenga tanta documentazione, include un codice di esempio per il passaggio comandi come start, stop e restart. Crea anche un file PID che può essere utile per verificare se il daemon è già in esecuzione ecc.

Questi esempi spiegano entrambi come creare il demone. Ci sono altre cose che devono essere considerate? Un campione è migliore dell'altro e perché?

È stato utile?

Soluzione

Soluzione attuale

Un'implementazione di riferimento di PEP 3143 (Libreria dei processi daemon standard) è ora disponibile come python-daemon .

Risposta storica

Il codice

Altri suggerimenti

Ci sono molte cose complicate di cui occuparsi quando si diventa un processo demone ben educato :

  • impedisce i core dump (molti daemon vengono eseguiti come root e i core dump possono contenere informazioni riservate)

  • si comportano correttamente all'interno di un chroot gaol

  • imposta UID, GID, directory di lavoro, umask e altri parametri di processo in modo appropriato per il caso d'uso

  • rinuncia ai privilegi suid , sgid elevati

  • chiude tutti i descrittori di file aperti, con esclusioni a seconda del caso d'uso

  • si comportano correttamente se avviato in un contesto già distaccato, come init , inetd , ecc.

  • imposta gestori di segnale per comportamenti demoni sensibili, ma anche con gestori specifici determinati dal caso d'uso

  • reindirizza i flussi standard stdin , stdout , stderr poiché un processo daemon non ha più un terminale di controllo

  • gestisce un file PID come blocco consultivo cooperativo, che è un intera lattina di worm in sé con molti modi contraddittori ma validi di comportamento

  • consente un'adeguata pulizia al termine del processo

  • in realtà diventa un processo daemon senza portare a zombi

Alcuni di questi sono standard , come descritto nella letteratura canonica Unix ( Programmazione avanzata in ambiente UNIX , del compianto W. Richard Stevens, Addison-Wesley, 1992 ). Altri, come il reindirizzamento dello stream e Gestione dei file PID , sono comportamento convenzionale che la maggior parte degli utenti demoni si aspettano, ma che sono meno standardizzati.

Tutti questi sono coperti da PEP 3143 & # 8220; Libreria dei processi daemon standard & # 8221; specifica . L'implementazione di riferimento python-daemon funziona su Python 2.7 o versione successiva e Python 3.2 o versione successiva .

Ecco il mio demone Python "Howdy World" di base con cui inizio, quando sto sviluppando una nuova applicazione demone.

#!/usr/bin/python
import time
from daemon import runner

class App():
    def __init__(self):
        self.stdin_path = '/dev/null'
        self.stdout_path = '/dev/tty'
        self.stderr_path = '/dev/tty'
        self.pidfile_path =  '/tmp/foo.pid'
        self.pidfile_timeout = 5
    def run(self):
        while True:
            print("Howdy!  Gig'em!  Whoop!")
            time.sleep(10)

app = App()
daemon_runner = runner.DaemonRunner(app)
daemon_runner.do_action()

Nota che avrai bisogno della libreria python-daemon . Puoi installarlo tramite:

pip install python-daemon

Quindi basta avviarlo con ./howdy.py start e fermarlo con ./howdy.py stop .

Nota il pacchetto python-daemon che risolve molti problemi alla base dei demoni della scatola.

Tra le altre funzionalità che abilita (dalla descrizione del pacchetto Debian):

  • Scollega il processo nel suo gruppo di processi.
  • Imposta l'ambiente di processo appropriato per l'esecuzione all'interno di un chroot.
  • Rinuncia ai privilegi di suid e sgid.
  • Chiudi tutti i descrittori di file aperti.
  • Cambia la directory di lavoro, uid, gid e umask.
  • Imposta gestori di segnale appropriati.
  • Apri nuovi descrittori di file per stdin, stdout e stderr.
  • Gestisci un file di blocco PID specificato.
  • Registra le funzioni di pulizia per l'elaborazione all'uscita.

Un'alternativa: crea un normale programma Python non daemonizzato, quindi esegui la demonizzazione esternamente utilizzando supervisord . Questo può risparmiare un sacco di mal di testa ed è * nix- e linguaggio-portatile.

Probabilmente non è una risposta diretta alla domanda, ma systemd può essere usato per eseguire la tua applicazione come demone. Ecco un esempio:

[Unit]
Description=Python daemon
After=syslog.target
After=network.target

[Service]
Type=simple
User=<run as user>
Group=<run as group group>
ExecStart=/usr/bin/python <python script home>/script.py

# Give the script some time to startup
TimeoutSec=300

[Install]
WantedBy=multi-user.target

Preferisco questo metodo perché gran parte del lavoro è fatto per te, e quindi il tuo script daemon si comporta in modo simile al resto del tuo sistema.

-Orby

poiché python-daemon non ha ancora supportato python 3.xe da ciò che può essere letto nella mailing list, potrebbe non esserlo mai, ho scritto una nuova implementazione di PEP 3143: pep3143daemon

pep3143daemon dovrebbe supportare almeno python 2.6, 2.7 e 3.x

Contiene anche una classe PidFile.

La libreria dipende solo dalla libreria standard e dal modulo sei.

Può essere usato come drop in sostituzione di python-daemon.

Ecco la documentazione .

YapDi è un modulo Python relativamente nuovo che è apparso in Hacker News. Sembra piuttosto utile, può essere usato per convertire uno script Python in modalità demone dall'interno dello script.

Questa funzione trasformerà un'applicazione in un demone:

import sys
import os

def daemonize():
    try:
        pid = os.fork()
        if pid > 0:
            # exit first parent
            sys.exit(0)
    except OSError as err:
        sys.stderr.write('_Fork #1 failed: {0}\n'.format(err))
        sys.exit(1)
    # decouple from parent environment
    os.chdir('/')
    os.setsid()
    os.umask(0)
    # do second fork
    try:
        pid = os.fork()
        if pid > 0:
            # exit from second parent
            sys.exit(0)
    except OSError as err:
        sys.stderr.write('_Fork #2 failed: {0}\n'.format(err))
        sys.exit(1)
    # redirect standard file descriptors
    sys.stdout.flush()
    sys.stderr.flush()
    si = open(os.devnull, 'r')
    so = open(os.devnull, 'w')
    se = open(os.devnull, 'w')
    os.dup2(si.fileno(), sys.stdin.fileno())
    os.dup2(so.fileno(), sys.stdout.fileno())
    os.dup2(se.fileno(), sys.stderr.fileno())

Temo che il modulo demone menzionato da @Dustin non abbia funzionato per me. Invece ho installato python-daemon e ho usato il seguente codice:

# filename myDaemon.py
import sys
import daemon
sys.path.append('/home/ubuntu/samplemodule') # till __init__.py
from samplemodule import moduleclass 

with daemon.DaemonContext():
    moduleclass.do_running() # I have do_running() function and whatever I was doing in __main__() in module.py I copied in it.

Correre è facile

> python myDaemon.py

solo per completezza ecco il contenuto della directory samplemodule

>ls samplemodule
__init__.py __init__.pyc moduleclass.py

Il contenuto di moduleclass.py può essere

class moduleclass():
    ...

def do_running():
    m = moduleclass()
    # do whatever daemon is required to do.

Un'altra cosa a cui pensare quando demonizzare in python:

Se stai usando registrazione in python e vuoi continuare a usarlo dopo la demonizzazione, assicurati di chiamare close () sui gestori (in particolare i gestori di file).

Se non lo fai, il gestore può ancora pensare che i file siano aperti e i tuoi messaggi scompariranno semplicemente, in altre parole assicurati che il logger sappia che i suoi file sono chiusi!

Ciò presuppone che quando si demonizza la chiusura di TUTTI i descrittori di file aperti indiscriminatamente - invece si potrebbe provare a chiudere tutti tranne i file di registro (ma di solito è più semplice chiudere tutti quindi riaprire quelli desiderati).

Ho modificato alcune righe nell'esempio di codice di Sander Marechal (menzionato da @JeffBauer in la risposta accettata ) per aggiungere una risposta Metodo quit () che viene eseguito prima dell'arresto del daemon. Questo a volte è molto utile.

Eccolo qui.

Nota: non uso il " python-daemon " modulo perché la documentazione manca ancora (vedi anche molte altre domande SO) ed è piuttosto oscura (come avviare / arrestare correttamente un demone dalla riga di comando con questo modulo?)

Il modo più semplice per creare un demone con Python è usare il Twisted basato su eventi. Gestisce tutte le cose necessarie per la demonizzazione per te. Utilizza il Reactor Pattern per gestire le richieste simultanee.

Dopo alcuni anni e molti tentativi (ho provato tutte le risposte fornite qui, ma alla fine tutti hanno avuto piccoli inconvenienti), ora mi rendo conto che c'è un modo migliore di voler avviare, fermare, riavviare un demone direttamente da Python: utilizzare invece gli strumenti del sistema operativo.

Ad esempio, per Linux, invece di python myapp start e python myapp stop , lo faccio per avviare l'app:

screen -S myapp python myapp.py    
CTRL+A, D to detach

o schermo -dmS myapp python myapp.py su avviarlo e scollegarlo in un solo comando .

Quindi:

screen -r myapp

per ricollegarsi a questo terminale. Una volta nel terminal, è possibile utilizzare CTRL + C per fermarlo.

L'80% delle volte, quando la gente dice "demone", vogliono solo un server. Poiché la domanda non è perfettamente chiara su questo punto, è difficile dire quale possa essere il possibile dominio di risposte. Poiché un server è adeguato, inizia da lì. Se un "demone" effettivo " è effettivamente necessario (questo è raro), leggi su nohup come un modo per demonizzare un server.

Fino a quando non è effettivamente richiesto un demone reale, basta scrivere un semplice server.

Guarda anche la riferimento WSGI .

Guarda anche il Simple HTTP Server .

" Ci sono altre cose che devono essere considerate? & Quot; Sì. Circa un milione di cose. Quale protocollo? Quante richieste? Quanto tempo per soddisfare ogni richiesta? Con quale frequenza arriveranno? Userai un processo dedicato? Le discussioni? Sottoprocessi? Scrivere un demone è un grosso lavoro.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top