...

パッケージ exec

import "os/exec"
概要
目次

概要 ▾

exec パッケージは,外部コマンドを実行します。os.StartProcess をラップし, 標準入力と標準出力を別の機能にしたり,パイプで I/O と接続したり,他の調整を簡単に加えることができます。

C や他の言語からの "システム" ライブラリ呼び出しとは異なり, os/exec パッケージは意図的にシステムシェルを呼び出したり, glob パターンを展開したり,他の展開,パイプライン,シェルによって通常行われるリダイレクトを処理しません。 このパッケージは, C の "exec" ファミリーの関数のように動作します。 glob パターンを拡張するには,危険な入力をエスケープするように注意してシェルを直接呼び出すか,または path/filepath パッケージの Glob 関数を使用します。 環境変数を拡張するには,パッケージ os の ExpandEnv を使用してください。

このパッケージの例では, Unix システムを想定しています。 それらは Windows 上では動かないかもしれませんし, golang.org や godoc.org が使っている Go Playground では動いていません。

変数

ErrNotFound は,パス検索で実行可能ファイルが見つからなかった場合に発生するエラーです。

var ErrNotFound = errors.New("executable file not found in $PATH")

func LookPath

func LookPath(file string) (string, error)

LookPath は, PATH 環境変数で指定されたディレクトリ内でファイルという名前の実行可能ファイルを検索します。 ファイルにスラッシュが含まれている場合は,それが直接試行され, PATH は調べられません。 結果は絶対パスまたは現在のディレクトリからの相対パスになります。

コード:

path, err := exec.LookPath("fortune")
if err != nil {
    log.Fatal("installing fortune is in your future")
}
fmt.Printf("fortune is available at %s\n", path)

type Cmd

Cmd は準備中または実行中の外部コマンドを表します。

Run, Output ,または CombinedOutput メソッドを呼び出した後で Cmd を再利用することはできません。

type Cmd struct {
    // Path は実行するコマンドのパスです。
    //
    // これは,ゼロ以外の値に設定する必要がある唯一のフィールドです。
    // Path が相対パスの場合は, Dir を基準にして評価されます。
    Path string

    // Args は,コマンドを Args[0] として含む,コマンドライン引数を保持します。
    // Args フィールドが空または nil の場合, Run は {Path} を使用します。
    //
    // 通常の使用では, Path と Args の両方が Command を呼び出すことによって設定されます。
    Args []string

    // Env はプロセスの環境を指定します。
    // 各エントリは "key=value" という形式です。
    // Env が nil の場合,新しいプロセスは現在のプロセスの環境を使います。
    // Env に重複する環境キーが含まれている場合は,各重複キーのスライス内の最後の値のみが使用されます。
    // Windows の特殊なケースとして,欠落している場合は常に SYSTEMROOT が追加され,空の文字列に明示的に設定されません。
    Env []string

    // Dir はコマンドの作業ディレクトリを指定します。
    // Dir が空の文字列の場合, Run は呼び出しプロセスの現在のディレクトリでコマンドを実行します。
    Dir string

    // Stdin はプロセスの標準入力を指定します。
    //
    // Stdin が nil の場合,プロセスは null デバイス (os.DevNull) から読み込みます。
    //
    // Stdin が *os.File の場合,プロセスの標準入力はそのファイルに直接接続されています。
    //
    // それ以外の場合は,コマンドの実行中に別のゴルーチンが Stdin から読み取り,そのデータをパイプを介してコマンドに渡します。
    // この場合, Wait は,ゴルーチンが Stdin の終わり (EOF または読み取りエラー) に達したため,またはパイプへの書き込みがエラーを返したために,コピーが停止するまで完了しません。
    Stdin io.Reader

    // Stdout と Stderr はプロセスの標準出力とエラーを指定します。
    //
    // どちらかが nil の場合, Run は対応するファイルディスクリプタを null デバイス (os.DevNull) に接続します。
    //
    // どちらかが *os.File の場合,プロセスからの対応する出力はそのファイルに直接接続されます。
    //
    // それ以外の場合,コマンドの実行中に別のゴルーチンがパイプを介してプロセスから読み取り,そのデータを対応する Writer に配信します。
    // この場合,ゴルーチンが EOF に達するかエラーが発生するまで待機は完了しません。
    //
    // Stdout と Stderr が同じライターで, == と比較できる型がある場合,一度に 1 つのゴルーチンが Write を呼び出します。
    Stdout io.Writer
    Stderr io.Writer

    // ExtraFiles は,新しいプロセスによって継承される追加のオープンファイルを指定します。
    // 標準入力,標準出力,または標準エラーは含まれません。
    // nil 以外の場合,エントリ i はファイル記述子 3+i になります。
    //
    // ExtraFiles は Windows ではサポートされていません。
    ExtraFiles []*os.File

    // SysProcAttr は,オプションのオペレーティングシステム固有の属性を保持します。
    // Run は os.ProcAttr の Sys フィールドとして os.StartProcess に渡します。
    SysProcAttr *syscall.SysProcAttr

    // Process は,一度開始されたなら,内部のプロセスです。
    Process *os.Process

    // ProcessState には, Wait または Run の呼び出し後に使用可能な終了プロセスに関する情報が含まれています。
    ProcessState *os.ProcessState
    // エクスポートされていないフィールドがあります
}

func Command

func Command(name string, arg ...string) *Cmd

Command は与えられた引数で指定されたプログラムを実行するために Cmd 構造体を返します。

返された構造体の Path と Args のみを設定します。

name にパス区切り文字が含まれていない場合, Command は可能であれば LookPath を使用して名前を完全なパスに解決します。 それ以外の場合は,名前を Path として直接使用します。

返された Cmd の Args フィールドは,コマンド名とそれに続く arg の要素から構成されているので, arg はコマンド名自体を含んではいけません。 たとえば, Command("echo", "hello") のようになります。 Args[0] は常に名前であり,解決される可能性のあるパスではありません。

Windows では,プロセスはコマンドライン全体を 1 つの文字列として受け取り,独自の解析を行います。 Command は, CommandLineToArgvW を使用するアプリケーションと互換性のあるアルゴリズムを使用して, Args をコマンドライン文字列に結合し,引用符で囲みます (これが最も一般的な方法です) 。 注目すべき例外は msiexec.exe と cmd.exe (そしてすべてのバッチファイル) で,引用符で囲まれていないアルゴリズムが異なります。 これらの場合や他の同様の場合は,自分で引用符を付けて SysProcAttr.CmdLine に完全なコマンドラインを入力し, Args を空のままにすることができます。

コード:

cmd := exec.Command("tr", "a-z", "A-Z")
cmd.Stdin = strings.NewReader("some input")
var out bytes.Buffer
cmd.Stdout = &out
err := cmd.Run()
if err != nil {
    log.Fatal(err)
}
fmt.Printf("in all caps: %q\n", out.String())

例 (Environment)

コード:

cmd := exec.Command("prog")
cmd.Env = append(os.Environ(),
    "FOO=duplicate_value", // 無視される
    "FOO=actual_value",    // この値が使われます
)
if err := cmd.Run(); err != nil {
    log.Fatal(err)
}

func CommandContext 1.7

func CommandContext(ctx context.Context, name string, arg ...string) *Cmd

CommandContext は Command に似ていますが,コンテキストを含みます。

渡されたコンテキストは,コマンドがそれ自体で完了する前にコンテキストが終了した場合に, (os.Process.Kill を呼び出すことによって) プロセスを強制終了するために使用されます。

コード:

ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond)
defer cancel()

if err := exec.CommandContext(ctx, "sleep", "5").Run(); err != nil {
    // これは 100 ミリ秒後に失敗します。
    // 5 秒間の sleep は中断されます。
}

func (*Cmd) CombinedOutput

func (c *Cmd) CombinedOutput() ([]byte, error)

CombinedOutput はコマンドを実行し,結合した標準出力と標準エラーを返します。

コード:

cmd := exec.Command("sh", "-c", "echo stdout; echo 1>&2 stderr")
stdoutStderr, err := cmd.CombinedOutput()
if err != nil {
    log.Fatal(err)
}
fmt.Printf("%s\n", stdoutStderr)

func (*Cmd) Output

func (c *Cmd) Output() ([]byte, error)

Output はコマンドを実行し,その標準出力を返します。 返されるエラーは通常 *ExitError 型です。 c.Stderr が nil の場合, Output は ExitError.Stderr に値を設定します。

コード:

out, err := exec.Command("date").Output()
if err != nil {
    log.Fatal(err)
}
fmt.Printf("The date is %s\n", out)

func (*Cmd) Run

func (c *Cmd) Run() error

Run は指定されたコマンドを開始し,それが完了するのを待ちます。

コマンドが実行され, stdin, stdout ,および stderr のコピーに問題がなく,終了ステータス 0 で終了した場合,返されるエラーは nil です。

コマンドが開始されたが正常に完了しなかった場合,エラーの型は *ExitError です。 他の状況では他のエラー型が返されることがあります。

呼び出し側のゴルーチンが runtime.LockOSThread でオペレーティングシステムのスレッドをロックし,継承可能な OS レベルのスレッドの状態 (Linux や Plan 9 の名前空間など) を変更した場合,新しいプロセスは呼び出し元のスレッドの状態を継承します。

コード:

cmd := exec.Command("sleep", "1")
log.Printf("Running command and waiting for it to finish...")
err := cmd.Run()
log.Printf("Command finished with error: %v", err)

func (*Cmd) Start

func (c *Cmd) Start() error

Start は指定されたコマンドを開始しますが,それが完了するのを待ちません。

コマンドが終了すると, Wait メソッドは終了コードを返し,関連するリソースを解放します。

コード:

cmd := exec.Command("sleep", "5")
err := cmd.Start()
if err != nil {
    log.Fatal(err)
}
log.Printf("Waiting for command to finish...")
err = cmd.Wait()
log.Printf("Command finished with error: %v", err)

func (*Cmd) StderrPipe

func (c *Cmd) StderrPipe() (io.ReadCloser, error)

StderrPipe は,コマンド開始時にコマンドの標準エラーに接続されるパイプを返します。

コマンド出口を見た後に Wait はパイプを閉じるので,ほとんどの呼び出し側は自分でパイプを閉じる必要はありません。 ただし,パイプからのすべての読み取りが完了する前に Wait を呼び出すのは正しくありません。 同じ理由で, StderrPipe を使用するときに Run を使用するのは正しくありません。 慣用句については StdoutPipe の例を​​参照してください。

コード:

cmd := exec.Command("sh", "-c", "echo stdout; echo 1>&2 stderr")
stderr, err := cmd.StderrPipe()
if err != nil {
    log.Fatal(err)
}

if err := cmd.Start(); err != nil {
    log.Fatal(err)
}

slurp, _ := ioutil.ReadAll(stderr)
fmt.Printf("%s\n", slurp)

if err := cmd.Wait(); err != nil {
    log.Fatal(err)
}

func (*Cmd) StdinPipe

func (c *Cmd) StdinPipe() (io.WriteCloser, error)

StdinPipe は,コマンドの開始時にコマンドの標準入力に接続されるパイプを返します。 Wait がコマンド出口を見た後でパイプは自動的に閉じられます。 呼び出し側はパイプを早く閉じるために Close を呼び出すだけです。 たとえば,実行中のコマンドが標準入力が閉じられるまで終了しない場合は,呼び出し側はパイプを閉じる必要があります。

コード:

cmd := exec.Command("cat")
stdin, err := cmd.StdinPipe()
if err != nil {
    log.Fatal(err)
}

go func() {
    defer stdin.Close()
    io.WriteString(stdin, "values written to stdin are passed to cmd's standard input")
}()

out, err := cmd.CombinedOutput()
if err != nil {
    log.Fatal(err)
}

fmt.Printf("%s\n", out)

func (*Cmd) StdoutPipe

func (c *Cmd) StdoutPipe() (io.ReadCloser, error)

StdoutPipe は,コマンドの開始時にコマンドの標準出力に接続されるパイプを返します。

コマンド出口を見た後に Wait はパイプを閉じるので,ほとんどの呼び出し側は自分でパイプを閉じる必要はありません。 ただし,パイプからのすべての読み取りが完了する前に Wait を呼び出すのは正しくありません。 同じ理由で, StdoutPipe を使用しているときに Run を呼び出すことは正しくありません。 慣用句については例を参照してください。

コード:

cmd := exec.Command("echo", "-n", `{"Name": "Bob", "Age": 32}`)
stdout, err := cmd.StdoutPipe()
if err != nil {
    log.Fatal(err)
}
if err := cmd.Start(); err != nil {
    log.Fatal(err)
}
var person struct {
    Name string
    Age  int
}
if err := json.NewDecoder(stdout).Decode(&person); err != nil {
    log.Fatal(err)
}
if err := cmd.Wait(); err != nil {
    log.Fatal(err)
}
fmt.Printf("%s is %d years old\n", person.Name, person.Age)

func (*Cmd) String 1.13

func (c *Cmd) String() string

文字列は,人間が読める c の説明を返します。デバッグのみを目的としています。特に,シェルへの入力としての使用には適していません。 String の出力は, Go のリリースによって異なる場合があります。

func (*Cmd) Wait

func (c *Cmd) Wait() error

Wait は,コマンドが終了するのを待ち, stdin へのコピー,または stdout または stderr からのコピーが完了するのを待ちます。

コマンドは Start によって開始されていなければなりません。

コマンドが実行され, stdin, stdout ,および stderr のコピーに問題がなく,終了ステータス 0 で終了した場合,返されるエラーは nil です。

コマンドが実行に失敗した場合,または正常に完了しなかった場合,エラーは型 *ExitError です。 I/O 問題に対して他のエラー型が返されることがあります。

c.Stdin, c.Stdout ,または c.Stderr のいずれかが *os.File ではない場合, Wait はそれぞれの入出力ループがプロセスとの間でコピーを完了するのを待ちます。

Wait は, Cmd に関連したすべてのリソースを解放します。

type Error

Error は,ファイルが実行可能ファイルとして分類されなかった場合, LookPath によって返されます。

type Error struct {
    // Name はエラーが発生したファイル名です。
    Name string
    // Err は根本的なエラーです。
    Err error
}

func (*Error) Error

func (e *Error) Error() string

func (*Error) Unwrap 1.13

func (e *Error) Unwrap() error

type ExitError

ExitError は,コマンドによる失敗した終了を報告します。

type ExitError struct {
    *os.ProcessState

    // 標準エラーが他に収集されていない場合, Stderr は Cmd.Output メソッドからの標準エラー出力のサブセットを保持します。
    //
    // エラー出力が長い場合, Stderr は出力のプレフィックスとサフィックスのみを含み,中間部分は省略されたバイト数に関するテキストに置き換えられます。
    //
    // エラーメッセージに含めるために, Stderr はデバッグ用に渡されています。
    // 他のニーズを持つユーザーは,必要に応じて Cmd.Stderr をリダイレクトする必要があります。
    Stderr []byte // Go 1.6
}

func (*ExitError) Error

func (e *ExitError) Error() string