web-dev-qa-db-ja.com

Goの子プロセスの標準出力パイプをリダイレクトする

Go(プログラム)のようなサーバー(Go)も実行するプログラムをGoで書いています。ここで、親プログラムを開始したターミナルウィンドウで子プログラムの標準出力を取得します。これを行う1つの方法はcmd.Output()関数を使用することですが、これはプロセスが終了した後にのみ標準出力を出力します。 (これは問題です。このサーバーのようなプログラムが長時間実行され、ログ出力を読みたいためです)

変数outは_type io.ReadCloser_であり、タスクを達成するためにそれをどうすればよいかわかりません。また、このトピックに関するWebで役立つ情報は見つかりません。

_func main() {
    cmd := exec.Command("/path/to/my/child/program")
    out, err := cmd.StdoutPipe()
    if err != nil {
        fmt.Println(err)
    }
    err = cmd.Start()
    if err != nil {
        fmt.Println(err)
    }
    //fmt.Println(out)
    cmd.Wait()
} 
_

コードの説明:Println関数のコメントを外して、コードをコンパイルします。Println(out io.ReadCloser)は意味のある関数ではないことを知っています。
(出力_&{3 |0 <nil> 0}_を生成します)これらの2行は、コードをコンパイルするために必要です。

93
mbert

ここで、親プログラムを開始したターミナルウィンドウで子プログラムの標準出力を取得します。

パイプやゴルーチンをいじる必要はありません。これは簡単です。

func main() {
    // Replace `ls` (and its arguments) with something more interesting
    cmd := exec.Command("ls", "-l")
    cmd.Stdout = os.Stdout
    cmd.Stderr = os.Stderr
    cmd.Run()
}
188
cmccabe

ioosをインポートしてこれを置き換えると、私は信じます:

//fmt.Println(out)

これとともに:

go io.Copy(os.Stdout, out)

(ドキュメントを参照してください io.Copy および os.Stdout )、それはあなたが望むことをします。 (免責事項:テストされていません。)

ちなみに、標準出力と同じアプローチを使用することで、cmd.StderrPipeおよびos.Stderrを使用して、標準エラーもキャプチャすることができます。

18
ruakh

ループ内でこれを必要としないが、コマンド出力がcmd.Wait()ブロックなしで他のステートメントをブロックせずに端末にエコーすることを望む場合:

package main

import (
    "fmt"
    "io"
    "log"
    "os"
    "os/exec"
)

func checkError(err error) {
    if err != nil {
        log.Fatalf("Error: %s", err)
    }
}

func main() {
    // Replace `ls` (and its arguments) with something more interesting
    cmd := exec.Command("ls", "-l")

    // Create stdout, stderr streams of type io.Reader
    stdout, err := cmd.StdoutPipe()
    checkError(err)
    stderr, err := cmd.StderrPipe()
    checkError(err)

    // Start command
    err = cmd.Start()
    checkError(err)

    // Don't let main() exit before our command has finished running
    defer cmd.Wait()  // Doesn't block

    // Non-blockingly echo command output to terminal
    go io.Copy(os.Stdout, stdout)
    go io.Copy(os.Stderr, stderr)

    // I love Go's trivial concurrency :-D
    fmt.Printf("Do other stuff here! No need to wait.\n\n")
}
14
elimisteve