Maison  >  Article  >  développement back-end  >  Implémentation du démon Python

Implémentation du démon Python

巴扎黑
巴扎黑original
2017-08-16 13:39:281443parcourir

Scénario du démon

Considérez le scénario suivant : vous écrivez un programme de service python et le démarrez à partir de la ligne de commande, et votre session de ligne de commande est contrôlée par le terminal, et le service python devient une partie du processus enfant du programme de terminal. Donc, si vous fermez le terminal, le programme de ligne de commande se fermera également.

Pour rendre votre service python permanent dans le système sans être affecté par le terminal, vous devez le transformer en processus démon.

Le processus démon est un programme démon, qui est un programme exécuté en arrière-plan du système. Il est indépendant du terminal de contrôle et effectue certaines tâches périodiques ou déclenche des événements. Il est généralement nommé d'après la lettre ". d", comme les httpd , syslogd, systemd et dockerd communs, etc.

Implémentation du code

Python peut implémenter le processus démon très simplement. Le code et les commentaires correspondants sont donnés ci-dessous. Ce code s'exécute de manière stable dans un processus démon (réveil créé par moi-même) sur mon ordinateur local, et il n'y a eu aucun problème pour le moment.

# coding=utf8
import os
import sys
import atexit
def daemonize(pid_file=None):
    """
    创建守护进程
    :param pid_file: 保存进程id的文件
    :return:
    """
    # 从父进程fork一个子进程出来
    pid = os.fork()
    # 子进程的pid一定为0,父进程大于0
    if pid:
        # 退出父进程,sys.exit()方法比os._exit()方法会多执行一些刷新缓冲工作
        sys.exit(0)
    # 子进程默认继承父进程的工作目录,最好是变更到根目录,否则回影响文件系统的卸载
    os.chdir('/')
    # 子进程默认继承父进程的umask(文件权限掩码),重设为0(完全控制),以免影响程序读写文件
    os.umask(0)
    # 让子进程成为新的会话组长和进程组长
    os.setsid()
    # 注意了,这里是第2次fork,也就是子进程的子进程,我们把它叫为孙子进程
    _pid = os.fork()
    if _pid:
        # 退出子进程
        sys.exit(0)
    # 此时,孙子进程已经是守护进程了,接下来重定向标准输入、输出、错误的描述符(是重定向而不是关闭, 这样可以避免程序在 print 的时候出错)
    # 刷新缓冲区先,小心使得万年船
    sys.stdout.flush()
    sys.stderr.flush()
    # dup2函数原子化地关闭和复制文件描述符,重定向到/dev/nul,即丢弃所有输入输出
    with open('/dev/null') as read_null, open('/dev/null', 'w') as write_null:
        os.dup2(read_null.fileno(), sys.stdin.fileno())
        os.dup2(write_null.fileno(), sys.stdout.fileno())
        os.dup2(write_null.fileno(), sys.stderr.fileno())
    # 写入pid文件
    if pid_file:
        with open(pid_file, 'w+') as f:
            f.write(str(os.getpid()))
        # 注册退出函数,进程异常退出时移除pid文件
        atexit.register(os.remove, pid_file)

Résumez les étapes d'écriture d'un processus démon :

1. Forkez le processus enfant et quittez le processus parent

2. Le processus enfant modifie le répertoire de travail. (chdir), masque d'autorisation de fichier (umask), groupe de processus et groupe de session (setsid)

3. Le processus enfant bifurque le processus petit-fils et quitte le processus enfant

4. actualise le tampon et redirige l'entrée standard /Output/Error (généralement vers /dev/null, ce qui signifie rejet)

5 (Facultatif) pid est écrit dans le fichier

Comprenez quelques-uns. points clés

Pourquoi ? Fourcher deux fois

La première fourchette est d'échapper aux griffes du contrôle du terminal. La raison pour laquelle le processus parent se termine est que le terminal frappe le clavier ou lui envoie un signal lorsqu'il est fermé ; et le processus enfant forké devient un processus orphelin après le suicide du processus parent, et est ensuite repris par le processus d'initialisation. du système d'exploitation, il quitte donc le contrôle du terminal.

Donc en fait, le deuxième fork n'est pas nécessaire (le code de nombreux projets open source ne bifurque pas deux fois). C'est simplement par prudence d'empêcher le processus d'ouvrir à nouveau un terminal de contrôle. Étant donné que le processus enfant est désormais le leader de la session (le premier processus de la session) et a la capacité d'ouvrir le terminal de contrôle, s'il se divise à nouveau, le processus petit-enfant ne pourra pas ouvrir le terminal de contrôle.

Descripteur de fichier

Linux est "tout est un fichier". Le descripteur de fichier est l'index créé par le noyau pour le fichier ouvert, généralement un entier non négatif. Les processus effectuent des opérations d'E/S via des descripteurs de fichiers.

Chaque processus a sa propre table de descripteurs de fichiers, donc le même descripteur peut pointer vers le même fichier ou différents fichiers ; différents descripteurs de différents processus peuvent bien sûr pointer vers le même fichier.

Par défaut, 0 représente l'entrée standard, 1 représente la sortie standard et 2 représente l'erreur standard.

Masque d'autorisation umask

Nous savons que sous Linux, tout fichier dispose de trois autorisations : lire, écrire et exécuter. Parmi eux, l'autorisation de lecture est représentée par le chiffre 4, l'autorisation d'écriture est 2 et l'autorisation d'exécution est 1. Vous pouvez vérifier les autorisations des fichiers avec la commande ls -l, et r/w/x signifie que vous disposez respectivement des autorisations de lecture/écriture/exécution.

Tout fichier dispose également de trois autorisations d'identité : Utilisateur, Groupe et Autres. Généralement, trois nombres sont utilisés pour représenter les autorisations de fichiers, tels que 754 :

7, qui est l'autorisation de l'utilisateur, c'est-à-dire l'autorisation du propriétaire du fichier

5, qui est l'autorisation du groupe. l'autorisation des membres du groupe d'utilisateurs où se trouve le propriétaire. Les autorisations dont il dispose

4 sont les autorisations Autres, c'est-à-dire les autorisations des utilisateurs d'autres groupes

et umask est de contrôlez les autorisations par défaut et empêchez les nouveaux fichiers ou dossiers d’avoir des autorisations complètes.

Le système utilise généralement la valeur par défaut 022 (utilisez la commande umask pour afficher), ce qui signifie que les autorisations par défaut pour la création de fichiers sont 644 et les dossiers sont 755. Vous devriez pouvoir voir leur modèle, c'est-à-dire que la somme des autorisations de fichiers et de l'umask est de 666 (rire), et la somme des autorisations des dossiers et de l'umask est de 777.

Groupe de processus

Chaque processus appartient à un groupe de processus (PG, Process Group), et un groupe de processus peut contenir plusieurs processus.

Le groupe de processus a un leader de processus (Leader), et l'ID du leader de processus (PID, Process ID) est utilisé comme ID de l'ensemble du groupe de processus (PGID, Process Groupd ID).

Groupe de sessions

Lorsque vous vous connectez au terminal, une session sera créée. Plusieurs groupes de processus peuvent être inclus dans une seule session. Le processus qui crée une session est le leader de la session.

Un processus qui est déjà le leader de la session ne peut pas appeler la méthode setsid() pour créer une session. Par conséquent, dans le code ci-dessus, le processus enfant peut appeler setsid(), mais le processus parent ne peut pas le faire car il est le leader de la session.

De plus, sh (Bourne Shell) ne prend pas en charge le mécanisme de session, car le mécanisme de session nécessite que le shell prenne en charge le contrôle des tâches (Job Control).

Processus démon et processus en arrière-plan

À l'aide du symbole &, les commandes peuvent être exécutées en arrière-plan. Il est différent du processus démon :

1. Le processus démon n'a rien à voir avec le terminal et est un processus orphelin adopté par le processus init tandis que le processus parent du processus d'arrière-plan est le terminal, il ; peut toujours imprimer sur le terminal

2. Le processus démon reste fort lorsque le terminal est fermé ; tandis que le processus en arrière-plan s'arrêtera lorsque l'utilisateur quittera, à moins que nohup

ne soit ajouté. Le processus démon modifie la session, le groupe de processus, le répertoire de travail et le descripteur de fichier. Le processus d'arrière-plan hérite directement du

du processus parent (shell).

En d'autres termes : le processus démon est le jeune homme prometteur qui travaille dur en silence, tandis que le processus d'arrière-plan est la riche deuxième génération qui hérite en silence des actifs de son père.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn