ホームページ  >  記事  >  バックエンド開発  >  Golang で子プロセスを正常にシャットダウンする方法

Golang で子プロセスを正常にシャットダウンする方法

PHPz
PHPzオリジナル
2023-04-25 09:19:261076ブラウズ

Golang は、マルチプロセス プログラミングをサポートする強力なプログラミング言語です。 Go で子プロセスを開始するのは簡単ですが、それを閉じるにはいくつかのコツが必要です。この記事では、Golang で子プロセスを正常にシャットダウンする方法を紹介します。

1. サブプロセスの開始
Golang でのサブプロセスの開始は非常に簡単で、exec パッケージの Command 関数を使用できます。コマンドの開始例を次に示します。

cmd := exec.Command("ls", "-l")
err := cmd.Start()
if err != nil {
    log.Fatal(err)
}

このコードは、「ls -l」コマンドの子プロセスを開始します。

2. 子プロセスを閉じる
子プロセスが完了したら、Wait 関数を呼び出して、子プロセスが閉じるのを待つ必要があります。ただし、子プロセスを無限ループで開始する場合、子プロセスをシャットダウンするには、より高度なテクニックが必要になります。

まず、子プロセスの PID を変数に保存する必要があります。これは、syscall パッケージの Getpid 関数を使用して実現できます。その後、子プロセスをシャットダウンする必要がある場合、syscall パッケージの Kill 関数を使用してオペレーティング システム シグナルを送信できます。

package main
 
import (
    "fmt"
    "os"
    "os/exec"
    "syscall"
    "time"
)
 
func main() {
    cmd := exec.Command("sleep", "10")
    err := cmd.Start()
    if err != nil {
        fmt.Println(err)
        os.Exit(1)
    }
 
    pid := cmd.Process.Pid
 
    fmt.Printf("Child process started: %v\n", pid)
 
    time.AfterFunc(time.Second*5, func() {
        err := syscall.Kill(pid, syscall.SIGTERM)
        if err != nil {
            fmt.Println(err)
        } else {
            fmt.Printf("Child process %v terminated\n", pid)
        }
    })
 
    cmd.Wait()
 
    fmt.Println("Parent process exiting.")
}

このプログラムは、「sleep 10」コマンドで子プロセスを開始し、5 秒待ってから、SIGTERM シグナルを送信して子プロセスを強制終了します。 time.AfterFunc 関数を使用して 5 秒後に操作を実行し、syscall.Kill 関数を使用してシグナルを送信します。操作が完了したら、cmd.Wait 関数を使用して、子プロセスが閉じるのを待ちます。

3. 子プロセスを正常にシャットダウンする
上記の例では、子プロセスをシャットダウンするために SIGTERM シグナルを送信しました。このシグナルはプロセスによって捕捉され、プロセスはシグナルを捕捉した後にクリーンアップ作業を実行し、通常どおり終了します。

子プロセスがシグナルをキャッチしない場合は、SIGKILL シグナルを使用して子プロセスを強制的に閉じる必要があります。このシグナルは、プロセスにクリーンアップの機会を与えずに、プロセスを直接強制終了します。子プロセスを強制的に閉じると、プロセスが一時ファイルを残してシステム リソースを占有する可能性があります。

子プロセスを正常にシャットダウンするには、子プロセスに終了シグナルを送信します。このシグナルは子プロセスによってキャッチされ、キャッチ後にプロセスは安全にシャットダウンされます。

終了シグナルを使用するには、子プロセスのコードでシグナルをサポートする必要があります。 Golang では、これは OS パッケージの Signal 関数を通じて実現できます。終了シグナルをサポートするサブプロセスの例を次に示します。

package main
 
import (
    "fmt"
    "os"
    "os/signal"
    "syscall"
    "time"
)
 
func main() {
    fmt.Println("Child process started.")
 
    sigchan := make(chan os.Signal, 1)
    signal.Notify(sigchan, syscall.SIGTERM)
 
    go func() {
        <-sigchan
        fmt.Println("Received SIGTERM signal, exiting...")
        os.Exit(0)
    }()
 
    // Start doing some meaningful work.
    for {
        fmt.Println("Working...")
        time.Sleep(time.Second)
    }
}

このプログラムは無限ループを開始し、毎秒「Working...」を出力します。子プロセスのコードでは、シグナル チャネル sigchan を作成し、signal.Notify 関数を使用して SIGTERM シグナルをチャネルに送信します。

その後、信号を受信するまで無限ループで待機します。このシグナルを受信すると、終了メッセージを出力し、os.Exit 関数を使用してプロセスを終了します。

これで、終了シグナルをサポートするサブプロセスがすでにできました。次のコードを使用してそれを閉じることができます:

package main
 
import (
    "fmt"
    "os"
    "os/exec"
    "syscall"
    "time"
)
 
func main() {
    cmd := exec.Command("./child")
    err := cmd.Start()
    if err != nil {
        fmt.Println(err)
        os.Exit(1)
    }
 
    pid := cmd.Process.Pid
 
    fmt.Printf("Child process started: %v\n", pid)
 
    time.AfterFunc(time.Second*5, func() {
        err := syscall.Kill(pid, syscall.SIGTERM)
        if err != nil {
            fmt.Println(err)
        } else {
            fmt.Printf("Child process %v terminated\n", pid)
        }
    })
 
    cmd.Wait()
 
    fmt.Println("Parent process exiting.")
}

このプログラムは test1 コマンドのサブプロセスを開始し、5 秒間待機します次に、SIGTERM シグナルを送信して子プロセスを閉じます。通常の状況では、子プロセスは終了メッセージを出力して正常に終了するはずです。

要約すると、Golang では子プロセスを閉じることはそれほど難しくありません。 syscall パッケージの Kill 関数を使用してシグナルを送信したり、子プロセスのコードで終了シグナルをサポートして子プロセスを正常にシャットダウンしたりできます。

以上がGolang で子プロセスを正常にシャットダウンする方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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