首頁  >  文章  >  後端開發  >  如何在Go中執行命令並將其與父進程分離?

如何在Go中執行命令並將其與父進程分離?

Patricia Arquette
Patricia Arquette原創
2024-10-29 04:35:02960瀏覽

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

在Go 中運行命令並將其與進程分離

在Go 中,您可以以分離的方式執行命令,使其能夠運行獨立於您的程式。以下是實現此目的的方法:

程式碼:

<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>

此程式碼示範如何以分離的方式執行指令,使其能夠獨立於其他指令繼續運行父進程。它提供了諸如捕獲 stdout 和 stderr、獲取進程 ID 以及選擇性地向子進程發送信號等功能。

關鍵注意事項:

  • 請注意分離進程並不能阻止它在父進程退出時成為孤立進程,因為核心仍然保留對它的引用。
  • 使用 SysProcAttr.Setpgid 可以讓子程序獨立地保持活動狀態,但可能需要額外的操作在某些情況下進行處理。
  • 請務必使用 Wait() 以確保進程返回退出程式碼,並且您可以處理任何潛在的錯誤。
  • 使用 syscall.Reap() 進行清理殭屍程序以避免資源外洩。

以上是如何在Go中執行命令並將其與父進程分離?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn