いろいろ備忘録日記

主に .NET とか Go とか Python絡みのメモを公開しています。

Goメモ-141 (exec.Command で Context 付きでコマンド実行)

概要

よく忘れるのでメモメモ。

少し前に exec.Command について以下をメモしていました。

devlights.hatenablog.com

devlights.hatenablog.com

devlights.hatenablog.com

上の記事では 、コマンドの実行に exec.Command() を利用していましたが、context.Context を指定できる exec.CommandContext() というのもあります。こちらを利用すると、渡した context.Context が Done したタイミングでまだ実行中だった場合に kill signal を送って終了してくれます。

サンプル

package cmdexec

import (
    "context"
    "errors"
    "os/exec"
    "runtime"
    "time"

    "github.com/devlights/gomy/output"
)

// WithContext は、context.Context 付きでコマンドを実行するサンプルです。
func WithContext() error {
    if runtime.GOOS == "windows" {
        return errors.New("this example cannot run on Windows, sorry")
    }

    const (
        Shell = "/bin/bash"
    )

    var (
        rootCtx          = context.Background()
        mainCtx, mainCxl = context.WithCancel(rootCtx)
        procCtx, procCxl = context.WithTimeout(mainCtx, 500*time.Millisecond)
    )

    defer mainCxl()
    defer procCxl()

    var (
        cmd *exec.Cmd // コマンド
        err error     // エラー
    )

    //
    // コマンドは2秒かかるようにして実行するが、渡している context は 500ms でタイムアウトする
    //
    cmd = exec.CommandContext(procCtx, Shell, "-c", "sleep 2")
    err = cmd.Run()
    if err != nil {
        var exitErr *exec.ExitError
        if errors.Is(procCtx.Err(), context.DeadlineExceeded) && errors.As(err, &exitErr) {
            output.Stdoutf("[timeout]", "%[1]v(%[1]T)\n", err)
            return nil
        } else {
            return err
        }
    }

    return nil
}

try-golang/withcontext.go at master · devlights/try-golang · GitHub

実行すると以下のようになります。

gitpod /workspace/try-golang $ make run

go get -d ./...
go run -race github.com/devlights/try-golang/cmd/trygolang -onetime -example ""

ENTER EXAMPLE NAME: cmdexec_withc
[Name] "cmdexec_withcontext"

[timeout]            signal: killed(*exec.ExitError)


[Elapsed] 502.113094ms

2秒かからずに渡した context が done したタイミングで終了してくれていますね。

参考資料

golang.org


過去の記事については、以下のページからご参照下さい。

  • いろいろ備忘録日記まとめ

devlights.github.io

サンプルコードは、以下の場所で公開しています。

  • いろいろ備忘録日記サンプルソース置き場

github.com

github.com

github.com