Maison  >  Article  >  développement back-end  >  Comment arrêter gracieusement les processus enfants dans Golang

Comment arrêter gracieusement les processus enfants dans Golang

PHPz
PHPzoriginal
2023-04-25 09:19:261076parcourir

Golang est un langage de programmation puissant qui prend en charge la programmation multi-processus. Démarrer un processus enfant dans Go est simple, mais le fermer nécessite quelques astuces. Cet article explique comment arrêter progressivement les processus enfants dans Golang.

1. Démarrez le sous-processus
Démarrer le sous-processus dans Golang est très simple. Vous pouvez utiliser la fonction Command dans le package exec. Voici un exemple de démarrage d'une commande :

cmd := exec.Command("ls", "-l")
err := cmd.Start()
if err != nil {
    log.Fatal(err)
}

Ce code lancera un processus enfant de la commande "ls -l".

2. Fermez le processus enfant
Lorsque le processus enfant est terminé, nous devons appeler la fonction Wait pour attendre la fermeture du processus enfant. Cependant, si nous démarrons le processus enfant dans une boucle infinie, des astuces plus avancées sont nécessaires pour arrêter le processus enfant.

Tout d'abord, nous devons stocker le PID du processus enfant dans une variable. Ceci peut être réalisé en utilisant la fonction Getpid dans le package syscall. Ensuite, lorsque nous devons arrêter le processus enfant, nous pouvons utiliser la fonction Kill du package syscall pour envoyer un signal au système d'exploitation.

package main
 
import (
    "fmt"
    "os"
    "os/exec"
    "syscall"
    "time"
)
 
func main() {
    cmd := exec.Command("sleep", "10")
    err := cmd.Start()
    if err != nil {
        fmt.Println(err)
        os.Exit(1)
    }
 
    pid := cmd.Process.Pid
 
    fmt.Printf("Child process started: %v\n", pid)
 
    time.AfterFunc(time.Second*5, func() {
        err := syscall.Kill(pid, syscall.SIGTERM)
        if err != nil {
            fmt.Println(err)
        } else {
            fmt.Printf("Child process %v terminated\n", pid)
        }
    })
 
    cmd.Wait()
 
    fmt.Println("Parent process exiting.")
}

Ce programme démarrera un processus enfant avec la commande "sleep 10", puis attendra 5 secondes puis enverra le signal SIGTERM pour tuer le processus enfant. Nous utilisons la fonction time.AfterFunc pour effectuer l'opération après 5 secondes et la fonction syscall.Kill pour envoyer le signal. Une fois l'opération terminée, nous utilisons la fonction cmd.Wait pour attendre la fermeture du processus enfant.

3. Fermez le processus enfant avec élégance
Dans l'exemple ci-dessus, nous avons envoyé un signal SIGTERM pour fermer le processus enfant. Ce signal sera capté par le processus, et le processus pourra effectuer un travail de nettoyage après avoir capté le signal, puis se terminer normalement.

Si le processus enfant ne capte pas le signal, nous devons utiliser le signal SIGKILL pour fermer de force le processus enfant. Ce signal tuera le processus directement sans lui donner la moindre chance de se nettoyer. La fermeture forcée d'un processus enfant peut amener le processus à laisser des fichiers temporaires et à occuper des ressources système.

L'arrêt gracieux d'un processus enfant peut être obtenu en envoyant un signal de sortie au processus enfant. Ce signal peut être capté par un processus enfant et le processus s'arrête en toute sécurité après la capture.

Pour utiliser le signal de sortie, nous devons prendre en charge le signal dans le code du processus enfant. Dans Golang, cela peut être réalisé grâce à la fonction Signal du package os. Voici un exemple de sous-processus prenant en charge les signaux de sortie :

package main
 
import (
    "fmt"
    "os"
    "os/signal"
    "syscall"
    "time"
)
 
func main() {
    fmt.Println("Child process started.")
 
    sigchan := make(chan os.Signal, 1)
    signal.Notify(sigchan, syscall.SIGTERM)
 
    go func() {
        <-sigchan
        fmt.Println("Received SIGTERM signal, exiting...")
        os.Exit(0)
    }()
 
    // Start doing some meaningful work.
    for {
        fmt.Println("Working...")
        time.Sleep(time.Second)
    }
}

Ce programme démarre une boucle infinie qui affiche "Working..." chaque seconde. Dans le code du processus enfant, nous créons un canal de signal sigchan et utilisons la fonction signal.Notify pour envoyer le signal SIGTERM au canal.

Nous attendons ensuite dans une boucle infinie de recevoir ce signal. Une fois ce signal reçu, nous imprimons un message de sortie et terminons le processus en utilisant la fonction os.Exit.

Maintenant, nous avons déjà un sous-processus qui prend en charge les signaux de sortie. Nous pouvons utiliser le code suivant pour le fermer :

package main
 
import (
    "fmt"
    "os"
    "os/exec"
    "syscall"
    "time"
)
 
func main() {
    cmd := exec.Command("./child")
    err := cmd.Start()
    if err != nil {
        fmt.Println(err)
        os.Exit(1)
    }
 
    pid := cmd.Process.Pid
 
    fmt.Printf("Child process started: %v\n", pid)
 
    time.AfterFunc(time.Second*5, func() {
        err := syscall.Kill(pid, syscall.SIGTERM)
        if err != nil {
            fmt.Println(err)
        } else {
            fmt.Printf("Child process %v terminated\n", pid)
        }
    })
 
    cmd.Wait()
 
    fmt.Println("Parent process exiting.")
}

Ce programme démarrera un sous-processus avec la commande test1, attendra 5 secondes puis enverra le SIGTERM. signal pour fermer le sous-processus. Dans des circonstances normales, le processus enfant doit imprimer un message de sortie et se terminer normalement.

Pour résumer, clôturer un processus enfant n'est pas très difficile à Golang. Nous pouvons utiliser la fonction Kill dans le package syscall pour envoyer des signaux, ou prendre en charge les signaux de sortie dans le code du processus enfant pour arrêter correctement le processus enfant.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn