Démoniser un processus Python

introduction

J'ai lu le livre Je vois, processus Unix - les bases d'Unix apprises en Ruby. Il explique le concept d'un processus utilisant du code Ruby. J'ai été impressionné par le livre très facile à comprendre: joy:

Je voudrais remplacer une partie du code Ruby dans le livre par Python pour examen. Comme c'est un gros problème, j'ai implémenté la démonisation de processus que je pensais la plus pratique.

code

from datetime import datetime
import os
import sys
import time


def daemonize():
  """
Faites du processus un démon.
  """
  def fork():
    if os.fork():
      sys.exit()

  def throw_away_io():
    stdin = open(os.devnull, 'rb')
    stdout = open(os.devnull, 'ab+')
    stderr = open(os.devnull, 'ab+', 0)

    for (null_io, std_io) in zip((stdin, stdout, stderr),
                                 (sys.stdin, sys.stdout, sys.stderr)):
      os.dup2(null_io.fileno(), std_io.fileno())

  fork()
  os.setsid()
  fork()
  throw_away_io()


def create_empty_file():
  """
Produit un fichier texte avec l'heure actuelle comme nom de fichier.
Le processus pid qui produit ce fichier est entré dans le fichier.
  """
  now = datetime.now().strftime('%Y%m%d%H%M%S')

  filepath = os.path.join(os.path.dirname(os.path.abspath(__file__)),
                          f'tmp/{now}.txt')

  with open(filepath, 'w') as f:
    f.write(str(os.getpid()))


def create_empty_files(interval=60):
  """
interval créer chaque seconde_empty_file()Appeler.
  """
  while True:
    create_empty_file()
    time.sleep(interval)


if __name__ == '__main__':
  daemonize()
  create_empty_files()

Description de daemonize ()

À propos du premier os.fork ()

Le code ci-dessus appelle fork () deux fois.

def fork()
  if os.fork():
    sys.exit()

Dans os.fork (), le pid du processus enfant est retourné dans le processus parent, et 0 est retourné dans le processus enfant. Autrement dit, le processus parent se termine et le processus enfant survit.

À propos de os.setsid ()

os.setsid () est comme son nom l'indique setsid () /html/LDP_man-pages/man2/setsid.2.html) Appelle un appel système. Et setsid () fait trois choses [^ 1]:

  1. Créez une nouvelle session.
  2. Faites du processus d'appel le leader d'une nouvelle session.
  3. Détachez le processus du terminal de commande.

Cela fait que le processus enfant qui a appelé os.setsid () devient le leader de la nouvelle session (et le nouveau groupe de processus pour cette session) et n'a plus de terminal de contrôle. Cependant, il semble qu'il soit techniquement possible de réinitialiser le terminal de contrôle sur une session [^ 2].

À propos du deuxième os.fork ()

Le second os.fork () met fin au processus qui était le leader de la session et du groupe de processus et génère un nouveau processus enfant. Étant donné que le chef de session terminé n'a pas de terminal de contrôle et que le nouveau processus enfant n'est pas le chef de session, cela peut garantir qu'il n'aura jamais de terminal de contrôle. Le processus démon est terminé.

À propos de throw_away_io ()

def throw_away_io():
  stdin = open(os.devnull, 'rb')
  stdout = open(os.devnull, 'ab+')
  stderr = open(os.devnull, 'ab+', 0)

  for (null_io, std_io) in zip((stdin, stdout, stderr),
                               (sys.stdin, sys.stdout, sys.stderr)):
    os.dup2(null_io.fileno(), std_io.fileno())

Jetez tous les flux standard en les envoyant dans / dev / null. C'est parce que le processus démon n'a pas de terminal de contrôle, donc ces ressources ne sont plus nécessaires. La raison pour laquelle le flux standard est envoyé à / dev / null au lieu de se fermer est que le flux standard est toujours disponible de l'extérieur compte tenu du programme externe qui suppose l'utilisation du flux standard. Il semble que ce soit pour donner l'impression que c'est le cas.

Résultat d'exécution

$ python main.py
$ ps aux | grep -v grep | grep python
quanon            4621   0.0  0.0  2418360   2996   ??  S    11:46PM   0:00.00 python main.py
$ cat tmp/20170520234627.txt
4621⏎

Un processus de démon fait à la main continue de fonctionner en arrière-plan: innocent:

à la fin

Si vous en avez envie, je veux lire le code de python-daemon: lunettes de soleil:

référence

Livres

Web

[^ 1]: On suppose que le processus appelant n'est pas le chef du groupe de processus. [^ 2]: Aucun détail n'est mentionné dans le livre. Dans l'article Mécanisme du démon Unix, "Old System V Dans le système wiki / UNIX_System_V), j'ai pu connecter le terminal de contrôle au processus du chef de session plus tard, donc je le fais pour des raisons historiques. "

Recommended Posts

Démoniser un processus Python
Démonisez une application Web Python avec Supervisor
Mémorandum du processus de suppression de chaîne python
Algorithme A * (édition Python)
Créer un module Python
expression lambda de python ...
Remarque pour faire de python un démon
Créer un environnement Python
Python3> rond (a --b, 7)
J'ai effectué un processus de connexion / déconnexion en utilisant Python's Bottle.
Prendre une capture d'écran en Python
Créer un dictionnaire en Python
AtCoder ABC 178 Python (A ~ E)
Une route vers Python intermédiaire
[Python] Utiliser une séquence de chaînes
AtCoder ABC 176 Python (A ~ E)
La liste Python n'est pas une liste
Mémorandum sur la corrélation [Python]
Créer un bookmarklet en Python
Construire un environnement virtuel Python
Créer un tableau numpy python
Faites une loterie avec Python
J'ai fait un texte Python
Un mémorandum sur le simulacre de Python
AtCoder ABC 182 Python (A ~ D)
Créer un environnement Python hors ligne
Dessinez un cœur en Python
Créer un répertoire avec python
Construire un environnement virtuel Python
Traitez le XML avec Python.
Une note sur [python] __debug__
Construire un environnement Python sur Mac
Python a + = b et a = a + b sont différents
Un enregistrement de patcher un package python
[Python] Qu'est-ce qu'une fonction zip?
[Python] Qu'est-ce qu'une instruction with?
Ecrire une dichotomie en Python
Utilisez pymol comme bibliothèque python
Résoudre ABC163 A ~ C avec Python
Faites fonctionner l'imprimante de reçus avec python
Manuel de graphisme Python avec Matplotlib.
Toucher les objets Python d'Elixir
Appuyez sur une commande en Python (Windows)
J'ai fait un Line-bot avec Python!
Python
Explication ABC127 A, B, C (python)
Créer une interface graphique python à l'aide de tkinter
Créer un conteneur DI avec Python
IQ Bot Custom Logic (Python): rationaliser le traitement de remplacement en boucle
Construire un environnement Python sur Ubuntu
Python: une note sur les classes 1 "Résumé"
Dessiner une courbe Silverstone en utilisant Python
Traitez le résultat de l'exécution de Splunk en utilisant Python et enregistrez-le dans un fichier
Résoudre ABC166 A ~ D avec Python
Avez-vous besoin de Python re.compile?
Dessinez une matrice de diagramme de dispersion avec python
Un bref résumé de la collection Python
ABC166 en Python A ~ C problème
Créez un environnement virtuel avec Python!