在Go中重定向子进程的stdout管道

时间:2012-01-16 01:52:01

标签: go stdout command-line-interface

我正在Go中编写一个程序来执行类似程序的服务器(也是Go)。现在我想在我启动父程序的终端窗口中输入子程序的标准输出。一种方法是使用cmd.Output()函数,但只有在进程退出后才打印stdout。 (这是一个问题,因为这个类似服务器的程序运行了很长时间,我想读取日志输出)

变量out属于type io.ReadCloser,我不知道应该怎么做才能完成我的任务,而且我在网上找不到任何有用的信息。< / p>

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})只需要这两行来获取要编译的代码。

3 个答案:

答案 0 :(得分:187)

  

现在我希望在终端中拥有子程序的标准输出   我启动父程序的窗口。

无需弄乱管道或goroutines,这个很容易。

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()
}

答案 1 :(得分:17)

我相信如果你导入ioos并替换它:

//fmt.Println(out)

用这个:

go io.Copy(os.Stdout, out)

(参见文档for io.Copyfor os.Stdout),它会做你想要的。 (免责声明:未经测试。)

顺便说一句,您可能也希望通过使用与标准输出相同的方法捕获标准错误,但使用cmd.StderrPipeos.Stderr

答案 2 :(得分:14)

对于那些在循环中不需要它的人,但是希望命令输出回显到终端而不会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")
}