Maison  >  Article  >  développement back-end  >  Comment exécuter une commande en Go et la détacher du processus parent ?

Comment exécuter une commande en Go et la détacher du processus parent ?

Patricia Arquette
Patricia Arquetteoriginal
2024-10-29 04:35:02960parcourir

How to Execute a Command in Go and Detach It from the Parent Process?

Exécuter une commande dans Go et la détacher du processus

Dans Go, vous pouvez exécuter une commande de manière détachée, lui permettant de s'exécuter indépendamment de votre programme. Voici comment y parvenir :

Code :

<code class="go">package main

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

func main() {
    // Define the command and its arguments
    cmd := exec.Command("sleep", "120")

    // Set up the pipes for stdout and stderr
    stdoutPipe, err := cmd.StdoutPipe()
    if err != nil {
        log.Fatal(err)
    }
    stderrPipe, err := cmd.StderrPipe()
    if err != nil {
        log.Fatal(err)
    }

    // Start the command
    if err := cmd.Start(); err != nil {
        log.Fatal(err)
    }

    // Get the process ID (PID) of the child process
    pid := cmd.Process.Pid

    // Print the PID
    fmt.Printf("PID: %d\n", pid)

    // Read from the stdout and stderr pipes and log the output
    go func() {
        for {
            buf := make([]byte, 1024)
            n, err := stdoutPipe.Read(buf)
            if err != nil {
                log.Fatal(err)
            }
            fmt.Printf("stdout: %s", string(buf[:n]))
        }
    }()
    go func() {
        for {
            buf := make([]byte, 1024)
            n, err := stderrPipe.Read(buf)
            if err != nil {
                log.Fatal(err)
            }
            fmt.Printf("stderr: %s", string(buf[:n]))
        }
    }()

    // Wait for the command to finish
    if err := cmd.Wait(); err != nil {
        if exitErr := cmd.ProcessState.Sys().(syscall.WaitStatus).ExitStatus(); exitErr != 0 {
            log.Fatal(fmt.Sprintf("Error #48692663: Command exited with code %d", exitErr))
        } else {
            log.Printf("Command exited with exit code 0")
        }
    }

    // Optionally, keep the child process alive even after the parent process exits
    // This can be achieved by setting `cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}` before starting the command.

    // Example of sending a signal to the detached process
    if err := syscall.Kill(pid, os.Interrupt); err != nil {
        log.Fatalf("Error sending signal to process: %d: %s", pid, err)
    } else {
        fmt.Printf("Received ^C and forwarded to process %d\n", pid)
    }

    // Optionally, use `syscall.Reap()` to clean up any child processes that are terminated but not yet waited for.
}</code>

Ce code montre comment exécuter une commande de manière détachée, lui permettant de continuer à s'exécuter indépendamment de le processus parent. Il fournit des fonctionnalités telles que la capture de stdout et stderr, l'obtention de l'ID de processus et éventuellement l'envoi de signaux au processus enfant.

Considérations clés :

  • Notez que détacher un processus ne l'empêche pas de devenir orphelin à la sortie de son parent, car le noyau en détient toujours une référence.
  • L'utilisation de SysProcAttr.Setpgid peut maintenir le processus enfant en vie indépendamment, mais cela peut nécessiter des manipulation dans certains cas.
  • Assurez-vous d'utiliser Wait() pour vous assurer que le processus renvoie un code de sortie et que vous pouvez gérer toutes les erreurs potentielles.
  • Utilisez syscall.Reap() pour nettoyer processus zombies pour éviter les fuites de ressources.

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