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.
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()
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.
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]:
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].
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é.
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.
$ 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:
Si vous en avez envie, je veux lire le code de python-daemon: lunettes de soleil:
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