Heim > Backend-Entwicklung > Golang > Golang implementiert den Daemon-Prozess

Golang implementiert den Daemon-Prozess

王林
Freigeben: 2023-05-12 21:15:06
Original
1987 Leute haben es durchsucht

Mit der rasanten Entwicklung des Internets werden auf dem Server laufende Anwendungen immer wichtiger. Allerdings müssen Server häufig bestimmte Prozesse über einen längeren Zeitraum ausführen, was einen speziellen Prozess erfordert, um sie zu überwachen und sicherzustellen, dass sie immer ausgeführt werden. Dieser spezielle Prozess wird Daemon oder Daemon genannt. In diesem Artikel besprechen wir, wie man einen Daemon mit Golang implementiert.

Was ist ein Daemon?

Ein Daemon ist ein Prozess, der im Hintergrund läuft und weiter läuft. Typischerweise ist ein Daemon ein dienstähnliches Programm, das nicht mit dem Benutzer interagiert, sondern beim Starten der Maschine ausgeführt wird und nicht gestoppt wird, bis die Maschine heruntergefahren wird. Daemons überwachen normalerweise bestimmte Dienste oder Prozesse und starten sie automatisch neu, wenn sie nicht mehr funktionieren.

Warum brauchen wir einen Daemon?

Die Rolle des Daemons besteht darin, die Anwendung am Laufen zu halten, auch wenn ein Fehler in der Anwendung selbst dazu führt, dass sie nicht mehr ausgeführt wird. Wenn wir bestimmte Dienste ständig auf dem Server ausführen müssen, insbesondere einige Dienste, die über einen längeren Zeitraum ausgeführt werden müssen, können bei diesen Diensten während des laufenden Prozesses verschiedene Fehler auftreten, die dazu führen können, dass der Dienst nicht mehr ausgeführt wird. Zu diesem Zeitpunkt benötigen wir einen Mechanismus, um den Betriebsstatus des Dienstes automatisch zu überwachen und ihn automatisch neu zu starten, wenn der Dienst nicht mehr ausgeführt wird.

Wie implementiert man einen Daemon-Prozess?

In einer Linux-Umgebung können wir systemd oder init.d verwenden, um den Daemon-Prozess zu implementieren. In diesem Artikel besprechen wir jedoch, wie Sie mit Golang selbst einen Daemon-Prozess implementieren.

Zuerst müssen wir den Daemon-Prozess in der main()-Funktion des Programms einrichten. Das Folgende ist ein Beispielcode zum Einrichten des Daemons:

package main

import (
    "fmt"
    "os"
    "os/exec"
    "syscall"
)

func main() {
    cmd := exec.Command(os.Args[0], os.Args[1:]...)
    cmd.SysProcAttr = &syscall.SysProcAttr{Setsid: true}

    err := cmd.Start()
    if err != nil {
        fmt.Println("Start error:", err)
        os.Exit(1)
    }

    fmt.Println("Process pid:", cmd.Process.Pid)
    os.Exit(0)
}
Nach dem Login kopieren

Bevor wir den Daemon einrichten, müssen wir os.Args aufrufen, um alle Parameter der Anwendung abzurufen, und os verwenden /exec</ code> Modul, um es auszuführen. Beim Ausführen des Befehls müssen wir den Wert <code>Setsid auf true setzen, um sicherzustellen, dass eine neue Sitzung erstellt wird. Dadurch wird die Anwendung zum ersten Prozess in der neuen Prozessgruppe und neuen Sitzung. os.Args获得应用程序的所有参数,并使用os/exec模块的其中一个命令来运行它。在运行命令时,我们需要设置Setsid值为true,以确保创建新的会话。这会使应用程序成为新的进程组和新会话的首进程。

一旦我们设置了守护进程,我们需要定义如何处理操作系统的信号。以下是一个捕获操作系统信号的样例代码:

package main

import (
    "fmt"
    "os"
    "os/signal"
    "syscall"
)

func main() {
    // daemon code here...

    signalCh := make(chan os.Signal, 1)
    signal.Notify(signalCh, syscall.SIGTERM)
    signal.Notify(signalCh, syscall.SIGQUIT)
    signal.Notify(signalCh, syscall.SIGINT)

    select {
    case signal := <-signalCh:
        fmt.Printf("Received signal: %s
", signal)
    }
}
Nach dem Login kopieren

在这个例子中,我们使用信号来通知我们何时关闭守护进程。我们使用OS包的make()函数创建一个signalCh通道来接收信号,然后使用signal.Notify()向通道注册三个信号,分别是SIGTERM,SIGQUIT和SIGINT。这些信号是我们需要关注的信号,当守护进程收到它们时,它会终止当前进程。

为了确保守护进程达到我们的期望,我们还需要几个步骤。首先,守护进程需要改变工作目录并刷新文件描述符。以下是一个样例代码:

package main

import (
    "fmt"
    "os"
    "os/exec"
    "syscall"
)

func main() {
    if os.Getppid() != 1 {
        cmd := exec.Command(os.Args[0], os.Args[1:]...)
        cmd.SysProcAttr = &syscall.SysProcAttr{Setsid: true}

        err := cmd.Start()
        if err != nil {
            fmt.Println("Start error:", err)
            os.Exit(1)
        }

        fmt.Println("Process pid:", cmd.Process.Pid)
        os.Exit(0)
    }

    os.Chdir("/")
    syscall.Umask(0)

    file, err := os.OpenFile("/dev/null", os.O_RDWR, 0)
    if err != nil {
        fmt.Println("file open error:", err)
        os.Exit(1)
    }

    syscall.Dup2(int(file.Fd()), int(os.Stdin.Fd()))
    syscall.Dup2(int(file.Fd()), int(os.Stdout.Fd()))
    syscall.Dup2(int(file.Fd()), int(os.Stderr.Fd()))
    file.Close()

    // daemon code here...
}
Nach dem Login kopieren

在这个样例代码中,我们首先检查当前守护进程是否在init进程下运行。如果不是,则创建新的守护进程。如果是,则守护进程成为了新创建的会话的首进程。随后,守护进程需要改变工作目录并刷新文件描述符。通过我们使用os.Chdir()函数将工作目录更改为根目录,使用syscall.Umask()设置默认的文件权限,然后使用os.OpenFile()函数打开 /dev/null 文件作为新的标准输入、输出和错误输出,并使用syscall.Dup2()

Sobald wir den Daemon eingerichtet haben, müssen wir definieren, wie mit Signalen vom Betriebssystem umgegangen wird. Hier ist ein Beispielcode, der Betriebssystemsignale erfasst:

// daemon code here...
Nach dem Login kopieren
In diesem Beispiel verwenden wir Signale, um uns zu benachrichtigen, wann wir den Daemon herunterfahren müssen. Wir verwenden die Funktion make() des Betriebssystempakets, um einen Kanal signalCh zum Empfangen des Signals zu erstellen, und verwenden dann signal.Notify() drei zu registrieren Die Signale sind SIGTERM, SIGQUIT und SIGINT. Auf diese Signale müssen wir achten, und wenn der Daemon sie empfängt, beendet er den aktuellen Prozess.

Um sicherzustellen, dass der Daemon unseren Erwartungen entspricht, benötigen wir noch ein paar Schritte. Zunächst muss der Daemon das Arbeitsverzeichnis ändern und die Dateideskriptoren leeren. Das Folgende ist ein Beispielcode:
    rrreee
  • In diesem Beispielcode prüfen wir zunächst, ob der aktuelle Daemon unter dem init-Prozess läuft. Wenn nicht, erstellen Sie einen neuen Daemon. Wenn dies der Fall ist, wird der Daemon zum ersten Prozess der neu erstellten Sitzung. Anschließend muss der Daemon das Arbeitsverzeichnis ändern und die Dateideskriptoren aktualisieren. Mithilfe der Funktion os.Chdir() ändern wir das Arbeitsverzeichnis in das Stammverzeichnis, verwenden syscall.Umask(), um die Standarddateiberechtigungen festzulegen, und verwenden dann os. Die Funktion OpenFile() öffnet die Datei /dev/null als neue Standardeingabe, -ausgabe und Fehlerausgabe und verwendet die Funktion syscall.Dup2(), um alles zu kopieren Dateideskriptoren für die Nulldatei /dev/.
  • Nachdem wir den Dateideskriptor geleert haben, platzieren wir schließlich den gesamten Daemon-bezogenen Code an der folgenden Stelle.
  • rrreee
  • Vorteile des Golang-Daemons

Golang ist sehr einfach zu verwalten und eignet sich für Anfänger.

Golang verfügt über eine gute Parallelität und Speicherverwaltung, wodurch Daemons unter hoher Last stabiler laufen können Plattformen, sodass Sie einen Daemon einmal entwickeln und auf mehreren Plattformen ausführen können.

🎜🎜Zusammenfassung🎜🎜In diesem Artikel haben wir gesehen, wie man mit Golang einen Daemon erstellt. Durch die Verwendung von Systemaufrufen und Signalverarbeitung kann der Golang-Daemon problemlos sicherstellen, dass die Anwendung weiterhin ausgeführt wird, und einige lang laufende Dienste problemlos überwachen und starten. Darüber hinaus bieten in Golang geschriebene Daemons die Vorteile einer plattformübergreifenden, leistungsstarken Speicherverwaltung und einer hohen Parallelitätsleistung und können zur Entwicklung verschiedener Anwendungen verwendet werden. 🎜

Das obige ist der detaillierte Inhalt vonGolang implementiert den Daemon-Prozess. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Quelle:php.cn
Erklärung dieser Website
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
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage