Maison > Article > développement back-end > Exemple de la façon dont Python implémente un processus démon
Démon : généralement défini comme un processus en arrière-plan et n'appartient à aucune session de terminal. De nombreux services système sont implémentés par des démons tels que les services réseau, l'impression, etc. L'article suivant partage avec vous un exemple de la façon dont Python implémente un processus démon. Les amis dans le besoin peuvent s'y référer.
Paramètre du scénario :
Vous avez écrit un programme de service Python et l'avez démarré à partir de la ligne de commande, et votre session de ligne de commande a été contrôlée par le terminal, le service python devient un sous-processus du programme du 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. la lettre "d", comme Common httpd, syslogd, systemd et dockerd, 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 :
# 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)
Décrivez les étapes d'écriture d'un démon :
débourser le processus , quittez le processus parent
Le processus enfant modifie le répertoire de travail (chdir), le masque d'autorisation de fichier (umask), le groupe de processus et le groupe de session (setsid)
Le processus enfant bifurque le processus petit-fils et quitte le processus enfant
Le processus petit-fils actualise le tampon et redirige les entrées/sorties/erreurs standard (généralement vers /dev/null , ce qui signifie rejeter)
(Facultatif) pid écrit dans le fichier
Comprendre plusieurs points clés
Pourquoi bifurquer 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.
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 a trois fonctions : lire, écrire et exécuter des types de droits d'utilisation. 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. La commande ls -l peut vérifier les autorisations du fichier, r/w/x signifie respectivement les autorisations de lecture/écriture/exécution.
Tout fichier dispose également de trois autorisations d'identité : Utilisateur, Groupe et Autres. Généralement, 3 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 de groupe. , qui appartient au groupe d'utilisateurs du propriétaire Les autorisations des membres du groupe
4 sont les autorisations Autres, c'est-à-dire les autorisations des utilisateurs d'autres groupes
et umask est de contrôler les autorisations par défaut et d'empêcher de nouveaux fichiers ou fichiers. Clamp a pleine autorité.
Le système par défaut est généralement 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).
Démons et processus en arrière-plan
À l'aide du symbole &, les commandes peuvent être exécutées en arrière-plan. C'est différent du démon :
Le processus démon n'a rien à voir avec le terminal et est un processus orphelin adopté par le processus d'initialisation ; alors que le processus parent du processus d'arrière-plan est le terminal, il peut toujours imprimer sur le terminal
Le démon persiste lorsque le terminal est fermé ; le processus en arrière-plan s'arrête lorsque l'utilisateur quitte, à moins que nohup ne soit ajouté
Le démon modifie la session , groupe de processus, répertoire de travail et descripteur de fichier , le processus d'arrière-plan hérite directement du
du processus parent (shell). un jeune homme qui travaille dur en silence, tandis que le processus d'arrière-plan hérite silencieusement de la riche deuxième génération avec des actifs.
Pour des articles plus pertinents sur la façon d'implémenter des processus démons en Python, veuillez faire attention au site Web PHP chinois !