Heim  >  Artikel  >  Backend-Entwicklung  >  Implementierung des Python-Daemons

Implementierung des Python-Daemons

巴扎黑
巴扎黑Original
2017-08-16 13:39:281487Durchsuche

Daemon-Szenario

Stellen Sie sich das folgende Szenario vor: Sie schreiben ein Python-Dienstprogramm und starten es über die Befehlszeile. Ihre Befehlszeilensitzung wird vom Terminal gesteuert und der Python-Dienst wird Teil davon Untergeordneter Prozess 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 einige periodische Aufgaben aus oder löst Ereignisse aus. Es wird normalerweise nach dem Buchstaben „ benannt. d“, wie zum Beispiel die gängigen httpd , syslogd, systemd und dockerd usw.

Code-Implementierung

Python kann den Daemon-Prozess sehr einfach implementieren. Der Code und die entsprechenden Kommentare sind unten angegeben. Dieser Code läuft stabil in einem Daemon-Prozess (selbst erstellter Wecker) auf meinem lokalen Computer und es gab vorerst keine Probleme.

# 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)

Fassen Sie die Schritte zum Schreiben eines Daemon-Prozesses zusammen:

1. Verzweigen Sie den untergeordneten Prozess und beenden Sie den übergeordneten Prozess.

2. Der untergeordnete Prozess ändert das Arbeitsverzeichnis (chdir), Dateiberechtigungsmaske (umask), Prozessgruppe und Sitzungsgruppe (setsid)

3. Der untergeordnete Prozess verzweigt den Enkelprozess und verlässt den untergeordneten Prozess

4 Aktualisiert den Puffer und leitet die Standardeingabe /Output/Error um (normalerweise nach /dev/null, was bedeutet, dass sie verworfen wird)

5 (Optional) pid wird in die Datei geschrieben

Ein paar verstehen Wichtige Punkte

Warum? Zweimal abzweigen

Der erste Abzweig besteht darin, den Fängen der terminalen Kontrolle 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 verzweigte 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 sich 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 Kontrollterminal zu öffnen, kann der Enkelprozess bei einer erneuten Verzweigung das Kontrollterminal 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.

Jeder Prozess verfügt über eine eigene Dateideskriptortabelle, daher kann derselbe Deskriptor auf dieselbe Datei verweisen, oder es können natürlich auch verschiedene Deskriptoren aus verschiedenen Prozessen auf dieselbe Datei verweisen.

Standardmäßig steht 0 für die Standardeingabe, 1 für die Standardausgabe und 2 für den Standardfehler.

umask-Berechtigungsmaske

Wir wissen, dass unter Linux jede Datei drei Berechtigungen hat: Lesen, Schreiben und Ausführen. 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 drei Zahlen verwendet, um Dateiberechtigungen darzustellen, z. B. 754:

7, was die Benutzerberechtigung ist, d. h. die Dateieigentümerberechtigung

5, was die Gruppenberechtigung ist die Berechtigungen der Mitglieder der Benutzergruppe, in der sich der Eigentümer befindet. Die Berechtigungen

4 sind „Andere“-Berechtigungen, also die Berechtigungen von Benutzern in anderen Gruppen

und umask Steuern Sie die Standardberechtigungen und verhindern Sie, dass neue Dateien oder Ordner über vollständige Berechtigungen verfügen.

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-Prozess und Hintergrundprozess

Mithilfe des &-Symbols können Befehle im Hintergrund ausgeführt werden. Es unterscheidet sich vom Daemon-Prozess:

1. Der Daemon-Prozess hat nichts mit dem Terminal zu tun und ist ein verwaister Prozess, der vom Init-Prozess übernommen wird kann weiterhin auf dem Terminal drucken

2. Der Daemon-Prozess bleibt aktiv, wenn das Terminal geschlossen wird, es sei denn, nohup

wird hinzugefügt Der Daemon-Prozess ändert die Sitzung, die Prozessgruppe, das Arbeitsverzeichnis und den Dateideskriptor. Der Hintergrundprozess erbt direkt das

des übergeordneten Prozesses (Shell).

Mit anderen Worten: Der Dämonprozess ist der vielversprechende junge Mann, der stillschweigend hart arbeitet, während der Hintergrundprozess die reiche zweite Generation ist, die stillschweigend das Vermögen seines Vaters erbt.

Das obige ist der detaillierte Inhalt vonImplementierung des Python-Daemons. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn