Heim  >  Artikel  >  Backend-Entwicklung  >  Wie führe ich einen Befehl in Go aus und trenne ihn vom übergeordneten Prozess?

Wie führe ich einen Befehl in Go aus und trenne ihn vom übergeordneten Prozess?

Patricia Arquette
Patricia ArquetteOriginal
2024-10-29 04:35:02960Durchsuche

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

Befehl in Go ausführen und vom Prozess trennen

In Go können Sie einen Befehl getrennt ausführen, sodass er ausgeführt werden kann unabhängig von Ihrem Programm. So können Sie dies erreichen:

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>

Dieser Code zeigt, wie ein Befehl getrennt ausgeführt wird, sodass er unabhängig davon weiter ausgeführt werden kann der übergeordnete Prozess. Es bietet Funktionen wie das Erfassen von stdout und stderr, das Abrufen der Prozess-ID und optional das Senden von Signalen an den untergeordneten Prozess.

Wichtige Überlegungen:

  • Beachten Sie Folgendes Das Trennen eines Prozesses verhindert nicht, dass er beim Beenden seines übergeordneten Prozesses verwaist, da der Kernel immer noch einen Verweis darauf enthält.
  • Mit SysProcAttr.Setpgid kann der untergeordnete Prozess unabhängig am Leben gehalten werden, es sind jedoch möglicherweise zusätzliche Prozesse erforderlich Behandlung in bestimmten Fällen.
  • Verwenden Sie unbedingt Wait(), um sicherzustellen, dass der Prozess einen Exit-Code zurückgibt und Sie mögliche Fehler behandeln können.
  • Verwenden Sie syscall.Reap() zum Bereinigen Zombie-Prozesse, um Ressourcenlecks zu vermeiden.

Das obige ist der detaillierte Inhalt vonWie führe ich einen Befehl in Go aus und trenne ihn vom übergeordneten Prozess?. 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