ホームページ  >  記事  >  バックエンド開発  >  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 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。