Question

Une recherche sur Google révèle des extraits de code x2. Le premier résultat est cette recette de code qui contient de nombreux documents et explications, ainsi que des discussion utile en dessous.

Cependant, un autre exemple de code ne contient pas tant de documentation mais comprend un exemple de code pour la transmission. commandes telles que démarrer, arrêter et redémarrer. Il crée également un fichier PID qui peut être utile pour vérifier si le démon est déjà en cours d'exécution, etc.

.

Ces exemples expliquent comment créer le démon. Y a-t-il d'autres choses à considérer? Un échantillon est-il meilleur que l'autre et pourquoi?

Était-ce utile?

La solution

Solution actuelle

Une implémentation de référence de PEP 3143 (bibliothèque de processus standard de démon) est maintenant disponible en tant que python-daemon .

Réponse historique

code de Sander Marechal sample est supérieur à l'original, qui avait été mis en ligne en 2004. Auparavant, j'avais déjà fourni un démoniseur pour Pyro, mais j'utiliserais probablement le code de Sander si je devais le refaire.

Autres conseils

Il y a beaucoup de choses difficiles à prendre en compte pour devenir processus démon bien comporté :

  • empêchez les vidages principaux (de nombreux démons s'exécutent en tant que root et les vidages principaux peuvent contenir des informations sensibles)

  • se comporte correctement dans un chroot gaol

  • définissez l'UID, le GID, le répertoire de travail, l'umask et d'autres paramètres de processus de manière appropriée pour le cas d'utilisation

  • abandonne le suid , les privilèges sgid

  • ferme tous les descripteurs de fichiers ouverts, avec des exclusions en fonction du cas d'utilisation

  • se comporte correctement s'il est démarré dans un contexte déjà détaché, tel que init , inetd , etc.

  • configurez des gestionnaires de signaux pour un comportement de démon sensible, mais également avec des gestionnaires spécifiques déterminés par le cas d'utilisation

  • redirigez les flux standard stdin , stdout , stderr puisqu'un processus démon n'a plus de terminal de contrôle

  • traite un fichier PID comme un verrou consultatif coopératif, qui est un ensemble de vers en soi avec de nombreuses façons contradictoires mais valables de se comporter

  • autoriser un nettoyage correct lorsque le processus est terminé

  • devient en réalité un processus démon sans générer de zombies

Certains d'entre eux sont standard , comme décrit dans la littérature canonique Unix ( Programmation avancée dans l'environnement UNIX ], par le regretté W. Richard Stevens, Addison-Wesley, 1992. ). Autres, tels que la redirection de flux et le traitement des fichiers PID . , sont des comportements conventionnels auxquels s'attendent la plupart des utilisateurs de démons, mais qui sont moins normalisés.

Tous ces éléments sont couverts par le PEP 3143 & # 8220; Bibliothèque de processus du démon standard & # 8221; spécification . L'implémentation de référence python-daemon fonctionne sur Python 2.7 ou version ultérieure, et Python 3.2 ou version ultérieure .

Voici le démon Python 'Howdy World' de base par lequel je commence lorsque je développe une nouvelle application démon.

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

Notez que vous aurez besoin de la bibliothèque python-daemon . Vous pouvez l'installer par:

pip install python-daemon

Il suffit ensuite de le démarrer avec ./ howdy.py start et de l'arrêter avec ./ howdy.py stop .

Notez le package python-daemon qui résout de nombreux problèmes derrière les démons de la boîte.

Entre autres fonctionnalités, il permet (à partir de la description du paquet Debian):

  • Détachez le processus dans son propre groupe de processus.
  • Définissez l'environnement de processus approprié pour une exécution dans un chroot.
  • Renoncez aux privilèges suid et sgid.
  • Fermez tous les descripteurs de fichiers ouverts.
  • Modifiez le répertoire de travail, uid, gid et umask.
  • Définissez les gestionnaires de signaux appropriés.
  • Ouvrez de nouveaux descripteurs de fichier pour stdin, stdout et stderr.
  • Gérer un fichier de verrouillage PID spécifié.
  • Enregistrez les fonctions de nettoyage pour le traitement en sortie.

Une alternative - créez un programme Python normal, non démonisé, puis démonisez-le en externe à l'aide de supervisord . Cela peut éviter beaucoup de maux de tête et est portable * avec nix et langue.

Probablement pas une réponse directe à la question, mais systemd peut être utilisé pour exécuter votre application en tant que démon. Voici un exemple:

[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

Je préfère cette méthode, car une grande partie du travail est effectuée pour vous, puis votre script démon se comporte de la même manière que le reste de votre système.

-Orby

python-daemon n'ayant pas encore pris en charge python 3.x, et d'après ce qui peut être lu sur la liste de diffusion, cela ne le sera jamais. J'ai écrit une nouvelle implémentation de PEP 3143: pep3143daemon

pep3143daemon devrait prendre en charge au moins les versions 2.6, 2.7 et 3.x de python

.

Il contient également une classe PidFile.

La bibliothèque ne dépend que de la bibliothèque standard et du module six.

Il peut être utilisé en remplacement instantané du démon python.

Voici la documentation .

YapDi est un module python relativement nouveau apparu dans Hacker News. Semble très utile, peut être utilisé pour convertir un script python en mode démon depuis le script.

Cette fonction transformera une application en démon:

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

J'ai bien peur que le module démon mentionné par @Dustin ne fonctionne pas pour moi. Au lieu de cela, j'ai installé python-daemon et utilisé le code suivant:

# 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.

Courir, c'est facile

> python myDaemon.py

juste pour compléter, voici le contenu du répertoire samplemodule

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

Le contenu de moduleclass.py peut être

class moduleclass():
    ...

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

Encore une chose à laquelle penser lors de la démonisation en python:

Si vous utilisez la journalisation et que vous souhaitez continuer à l'utiliser après la démonisation, veillez à appeler close () sur les gestionnaires (en particulier les gestionnaires de fichiers).

Si vous ne le faites pas, le gestionnaire peut toujours penser qu'il a des fichiers ouverts et vos messages disparaîtront tout simplement. En d'autres termes, assurez-vous que l'enregistreur sait que ses fichiers sont fermés!

Cela suppose que lorsque vous démonisez, vous fermez TOUS les descripteurs de fichiers ouverts sans distinction - vous pouvez essayer de fermer tous les fichiers sauf les fichiers journaux (mais il est généralement plus simple de tout fermer puis de rouvrir ceux que vous voulez).

J'ai modifié quelques lignes de l'exemple de code de Sander Marechal (mentionné par @JeffBauer dans réponse acceptée ) afin d'ajouter un Méthode quit () qui est exécutée avant l'arrêt du démon. C'est parfois très utile.

Le voici.

Remarque: je n'utilise pas le "démon python". module car la documentation est toujours manquante (voir aussi beaucoup d’autres questions SO) et assez obscure (comment démarrer / arrêter correctement un démon en ligne de commande avec ce module?)

Le moyen le plus simple de créer un démon avec Python consiste à utiliser le cadre Twisted . Il gère pour vous tout le matériel nécessaire à la démonisation. Il utilise le modèle de réacteur pour traiter les demandes simultanées.

Après quelques années et de nombreuses tentatives (j’ai essayé toutes les réponses données ici, mais toutes présentaient des inconvénients mineurs à la fin), je réalise maintenant qu’il existe un meilleur moyen que de vouloir démarrer, arrêter, redémarrer un démon. directement depuis Python: utilisez plutôt les outils du système d'exploitation.

Par exemple, pour Linux, au lieu de faire python myapp start et python myapp stop , je le fais pour démarrer l'application:

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

ou screen -dmS myapp python myapp.py pour démarrer et le détacher en une seule commande .

Ensuite:

screen -r myapp

pour relier à ce terminal. Une fois dans le terminal, il est possible d’utiliser CTRL + C pour l’arrêter.

80% du temps, quand les gens disent "démon", ils veulent seulement un serveur. Comme la question n’est pas claire sur ce point, il est difficile de dire quel pourrait être le domaine possible des réponses. Puisqu'un serveur est adéquat, commencez par là. Si un " démon " réel est réellement nécessaire (ce qui est rare), consultez nohup pour démoniser un serveur.

En attendant qu'un démon soit réellement nécessaire, il suffit d'écrire un serveur simple.

Consultez également la référence WSGI . .

Consultez également le serveur HTTP simple . .

"Y a-t-il d'autres éléments à prendre en compte? " Oui. Environ un million de choses. Quel protocole? Combien de demandes? Combien de temps pour traiter chaque demande? À quelle fréquence vont-ils arriver? Utiliserez-vous un processus dédié? Des fils? Sous-processus? Écrire un démon est un gros travail.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top