覚えたら書く

IT関係のデベロッパとして日々覚えたことを書き残したいです。twitter: @yyoshikaw

Go言語 - 外部コマンドを実行する

Go言語で外部コマンドを実行するには、execパッケージを利用します。(実際のimportはimport "os/exec"となります)

実行したいコマンドをexec.Command(<コマンド>)で生成して、生成したコマンドをCmd.RunCmd.Outputで実行する流れになります


Run - コマンドの完了を待つ

Cmd.Runを使うと実行したコマンドの完了を待ちます。ただし、コマンドが出力した結果などは受け取ることはできません

■サンプルコード

package main

import (
    "fmt"
    "os/exec"
)

func main() {
    err := exec.Command("C:/app/SampleApp.exe").Run()
    if err != nil {
        fmt.Println("Command Exec Error.")
    }
}


Output - コマンドの完了を待ち出力された結果も取得する

Cmd.Outputを使うと実行したコマンドが標準出力に出力した内容を戻り値で取得することができます

■サンプルコード

package main

import (
    "fmt"
    "os/exec"
)

func main() {
    out, err := exec.Command("ls", "-la").Output()
    if err != nil {
        fmt.Println("Command Exec Error.")
    }

    // 実行したコマンドの結果を出力
    fmt.Printf("ls result: \n%s", string(out))
}

■実行結果

ls result: 
total 32
drwxr-xr-x  6 user1 Administrators  4096 Apr 16 16:55 .
drwxr-xr-x 44 user1 Administrators 16384 Apr 15 09:34 ..
drwxr-xr-x  2 user1 Administrators     0 Apr 16 16:23 img
drwxr-xr-x 10 user1 Administrators  4096 Apr 16 19:25 sampleapp


ただし、Cmd.Outputを使った場合は標準エラー出力の内容は取得できません。
例えば存在しないディレクトリ指定でlsを実行すると標準エラー出力にエラー内容が出力されますが、それを取得することができません

■サンプルコード

package main

import (
    "fmt"
    "os/exec"
)

func main() {
    out, err := exec.Command("ls", "noexists").Output()
    if err != nil {
        fmt.Println("Command Exec Error.")
    }

    // 実行したコマンドの標準出力の内容
    fmt.Printf("ls result: \n%s", string(out))
}

■実行結果

ls result: 

実行結果の通り、標準エラー出力の内容を拾えていません。これを解決するには Cmd.CombinedOutputを使用します


CombinedOutput - 標準出力も標準エラー出力も取得する

Cmd.CombinedOutputを使うと実行したコマンドが標準出力と標準エラー出力に出力した内容を戻り値で取得することができます

■サンプルコード

package main

import (
    "fmt"
    "os/exec"
)

func main() {
    out, err := exec.Command("ls", "noexists").CombinedOutput()
    if err != nil {
        fmt.Println("Command Exec Error.")
    }

    // 実行したコマンドの標準出力+標準エラー出力の内容
    fmt.Printf("ls result: \n%s", string(out))
}

■実行結果

fmt.Println("Command Exec Error.")
ls result: 
ls: noexists: No such file or directory

標準エラー出力の内容を取得することができています


Start - コマンドの完了を待たない

Cmd.Startを実行するとコマンドの完了を待ちません。ただし、Cmd.Waitを組み合わせることで待ち合わせることもできます

■サンプルコード

package main

import (
    "fmt"
    "os/exec"
)

func main() {
    cmd := exec.Command("uname")

    fmt.Println("Command Start.")

    err := cmd.Start()
    if err != nil {
        fmt.Println("Command Exec Error.")
    }

    cmd.Wait()

    fmt.Println("Command Exit.")
}

■実行結果

Command Start.
Command Exit.