Maison >développement back-end >Golang >Comment détacher un processus de longue durée dans Go et éviter les zombies ?

Comment détacher un processus de longue durée dans Go et éviter les zombies ?

Linda Hamilton
Linda Hamiltonoriginal
2024-11-01 07:51:31252parcourir

How to Detach a Long-Running Process in Go and Avoid Zombies?

Exécutez la commande dans Go et détachez-la du processus

Problème :

Vous devez exécutez un processus de longue durée dans Go et assurez-vous que :

  • stdout est redirigé vers un fichier.
  • L'utilisateur du processus est contrôlé.
  • Le processus ne meurt pas à la fermeture de votre programme.
  • Le processus ne devient pas un zombie s'il plante.
  • Vous obtenez le PID du processus en cours d'exécution.

Tentative de solution :

Vous avez essayé d'utiliser cmd.Start() et cmd.Process.Release(), mais ils n'empêchent pas le processus de devenir un zombie à la fermeture de votre programme. Vous souhaitez également que le processus soit aussi séparé que possible, avec son propre PID parent, PID de groupe, etc.

Solution :

Le problème auquel vous êtes confronté est que Linux ne vous permet pas de changer le parent d'un processus une fois qu'il est démarré. Si vous voulez un processus vraiment détaché, il doit être démarré par autre chose, comme atd ou systemd.

Pour résoudre les problèmes liés aux zombies et à l'arrêt des processus, vous pouvez utiliser une bibliothèque comme [go-reap] (https://github.com/hashicorp/go-reap). Il fournit un service Reaper qui récolte automatiquement les processus enfants orphelins et signale leur statut de sortie.

Voici un exemple utilisant go-reap pour démarrer un processus détaché :

<code class="go">package main

import (
    "context"
    "fmt"
    "os/exec"

    "github.com/hashicorp/go-reap"
)

func main() {
    // Start a Reaper service to reap orphaned processes.
    doneCh := make(chan struct{})

    ctx, cancel := context.WithCancel(context.Background())
    reaper := reap.NewReaper(cancel)
    go reaper.Run(ctx)
    defer reaper.Stop()

    // Execute a command in a detached process.
    cmd := exec.Command("my-long-running-command", "args")

    pid, err := reaper.Reap(cmd)
    if err != nil {
        fmt.Printf("Error reaping process: %v\n", err)
        return
    }

    fmt.Printf("PID of detached process: %v\n", pid)

    // Wait for the detached process to complete.
    exitStatus, err := reaper.WaitPid(pid)
    if err != nil {
        fmt.Printf("Error waiting for process: %v\n", err)
        return
    }

    fmt.Printf("Detached process exited with status: %v\n", exitStatus)

    // Stop the Reaper service when done.
    close(doneCh)
}</code>

En utilisant go-reap et en récoltant le processus à sa sortie, vous pouvez vous assurer qu'il ne devient pas un zombie et que vous pouvez suivre son statut de sortie.

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