Heim >Backend-Entwicklung >Python-Tutorial >Beispiel dafür, wie Python einen Daemon-Prozess implementiert
Daemon: Wird normalerweise als Hintergrundprozess definiert und gehört zu keiner Terminalsitzung. Viele Systemdienste werden von Dämonen implementiert, z. B. Netzwerkdienste, Drucken usw. Der folgende Artikel zeigt Ihnen ein Beispiel dafür, wie Python einen Daemon-Prozess implementiert.
Szenarioeinstellung:
Sie haben ein Python-Dienstprogramm geschrieben und es über die Befehlszeile gestartet, und Ihre Befehlszeilensitzung wurde von gesteuert Terminal wird der Python-Dienst zu einem Unterprozess des Terminalprogramms. Wenn Sie also das Terminal schließen, wird auch das Befehlszeilenprogramm geschlossen.
Um Ihren Python-Dienst dauerhaft im System zu machen, ohne vom Terminal beeinflusst zu werden, müssen Sie ihn in einen Daemon-Prozess umwandeln.
Der Daemon-Prozess ist ein Daemon-Programm, das im Hintergrund des Systems ausgeführt wird. Es ist unabhängig vom Steuerterminal und führt normalerweise einige periodische Aufgaben aus oder löst Ereignisse aus der Buchstabe „d“, wie z. B. Common httpd, syslogd, systemd und dockerd usw.
Code-Implementierung
Python kann den Daemon-Prozess sehr einfach implementieren:
# 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)
Beschreiben Sie die Schritte zum Schreiben eines Daemons:
Fork-Out-Prozess , den übergeordneten Prozess verlassen
Der untergeordnete Prozess ändert das Arbeitsverzeichnis (chdir), die Dateiberechtigungsmaske (umask), die Prozessgruppe und die Sitzungsgruppe (setsid)
Der untergeordnete Prozess verzweigt den Enkelprozess und verlässt den untergeordneten Prozess
Der Enkelprozess aktualisiert den Puffer und leitet Standardeingaben/-ausgaben/-fehler um (normalerweise nach /dev/null). , was Verwerfen bedeutet)
(Optional) PID in Datei geschrieben
Mehrere wichtige Punkte verstehen
Warum zweimal forken?
Der erste Fork besteht darin, den Fängen der Terminalkontrolle zu entkommen. Der Grund für das Beenden des übergeordneten Prozesses liegt darin, dass das Terminal beim Schließen auf die Tastatur drückt oder ein Signal an sie sendet und der gegabelte untergeordnete Prozess zu einem verwaisten Prozess wird, nachdem der übergeordnete Prozess Selbstmord begangen hat, und dann vom Init-Prozess übernommen wird des Betriebssystems, so dass die Kontrolle über das Terminal erfolgt.
Die zweite Verzweigung ist also tatsächlich nicht notwendig (der Code in vielen Open-Source-Projekten verzweigt nicht zweimal). Dies dient nur der Vorsicht, um zu verhindern, dass der Prozess erneut ein Kontrollterminal öffnet. Da der untergeordnete Prozess jetzt der Sitzungsleiter ist (der erste Prozess in der Sitzung) und die Möglichkeit hat, das Steuerterminal zu öffnen, kann der untergeordnete Prozess bei einer erneuten Verzweigung das Steuerterminal nicht öffnen.
Dateideskriptor
Linux ist „Alles ist eine Datei“. Der Dateideskriptor ist der vom Kernel erstellte Index für die geöffnete Datei, normalerweise eine nicht negative Ganzzahl . Prozesse führen E/A-Vorgänge über Dateideskriptoren aus.
Standardmäßig steht 0 für die Standardeingabe, 1 für die Standardausgabe und 2 für den Standardfehler.
umask-Berechtigungsmaske
Wir wissen, dass jede Datei unter Linux drei Funktionen hat: Lese-, Schreib- und Ausführungsrechte. Unter diesen wird die Leseberechtigung durch die Zahl 4 dargestellt, die Schreibberechtigung ist 2 und die Ausführungsberechtigung ist 1. Der Befehl ls -l kann die Dateiberechtigungen überprüfen, r/w/x bedeutet jeweils Lese-/Schreib-/Ausführungsberechtigungen.
Jede Datei verfügt außerdem über drei Identitätsberechtigungen: Benutzer, Gruppe und Andere. Im Allgemeinen werden 3 Zahlen verwendet, um Dateiberechtigungen darzustellen, z. B. 754:
7, was die Benutzerberechtigung ist, also die Dateieigentümerberechtigung
5, was die Gruppenberechtigung ist , die zur Benutzergruppe des Besitzers gehört. Die Berechtigungen der Gruppenmitglieder
4 sind Andere Berechtigungen, also die Berechtigungen von Benutzern in anderen Gruppen
und umask Die Aufgabe besteht darin, die Standardberechtigungen zu steuern und neue Dateien oder Dateien zu verhindern. Clamp hat die volle Berechtigung.
Das System ist im Allgemeinen standardmäßig auf 022 eingestellt (verwenden Sie zum Anzeigen den Befehl umask), was bedeutet, dass die Standardberechtigungen zum Erstellen von Dateien 644 und für Ordner 755 sind. Sie sollten ihr Muster erkennen können, das heißt, die Summe aus Dateiberechtigungen und umask beträgt 666 (lacht) und die Summe aus Ordnerberechtigungen und umask beträgt 777.
Prozessgruppe
Jeder Prozess gehört zu einer Prozessgruppe (PG, Prozessgruppe), und eine Prozessgruppe kann mehrere Prozesse enthalten.
Die Prozessgruppe hat einen Prozessleiter (Leader), und die ID des Prozessleiters (PID, Process ID) wird als ID der gesamten Prozessgruppe (PGID, Process Groupd ID) verwendet.
Sitzungsgruppe
Wenn Sie sich am Terminal anmelden, wird eine Sitzung erstellt. In einer Sitzung können mehrere Prozessgruppen enthalten sein. Der Prozess, der eine Sitzung erstellt, ist der Sitzungsleiter.
Ein Prozess, der bereits Sitzungsleiter ist, kann die Methode setsid() nicht aufrufen, um eine Sitzung zu erstellen. Daher kann im obigen Code der untergeordnete Prozess setsid() aufrufen, der übergeordnete Prozess jedoch nicht, da er der Sitzungsleiter ist.
Darüber hinaus unterstützt sh (Bourne Shell) den Sitzungsmechanismus nicht, da der Sitzungsmechanismus erfordert, dass die Shell die Jobsteuerung (Job Control) unterstützt.
Daemon- und Hintergrundprozesse
Mithilfe des &-Symbols können Befehle im Hintergrund ausgeführt werden. Es unterscheidet sich vom Daemon:
Der Daemon-Prozess hat nichts mit dem Terminal zu tun und ist ein verwaister Prozess, der vom Init-Prozess übernommen wird. Während der übergeordnete Prozess des Hintergrundprozesses das Terminal ist, kann er dennoch auf dem Terminal drucken
Der Daemon bleibt bestehen, wenn das Terminal geschlossen wird; der Hintergrundprozess stoppt, wenn der Benutzer es verlässt, es sei denn, nohup wird hinzugefügt
Der Daemon ändert die Sitzung , Prozessgruppe, Arbeitsverzeichnis und Dateideskriptor, der Hintergrundprozess erbt direkt das
des übergeordneten Prozesses (Shell): Der Daemon-Prozess ist ein vielversprechender Prozess junger Mann, der im Stillen hart arbeitet, während der Hintergrundprozess stillschweigend von seinem Vater erbt. Die reiche zweite Generation mit Vermögen.
Weitere relevante Artikel zur Implementierung von Daemon-Prozessen in Python finden Sie auf der chinesischen PHP-Website!