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行は、コードをコンパイルするために必要です。
ここで、親プログラムを開始したターミナルウィンドウで子プログラムの標準出力を取得します。
パイプやゴルーチンをいじる必要はありません。これは簡単です。
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()
}
ループ内でこれを必要としないが、コマンド出力が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")
}