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

mbe*_*ert 99 stdout command-line-interface go

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

变量out是,type io.ReadCloser我不知道我应该怎么做才能完成我的任务,我在网上找不到任何有用的信息.

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()
} 
Run Code Online (Sandbox Code Playgroud)

代码说明:取消注释Println函数以获取编译代码,我知道这Println(out io.ReadCloser)不是一个有意义的函数.
(它产生输出&{3 |0 <nil> 0})这两行只是获取编译代码所必需的.

cmc*_*abe 194

现在我想在我启动父程序的终端窗口中输入子程序的标准输出.

不需要弄脏管道或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()
}
Run Code Online (Sandbox Code Playgroud)

  • 另外,如果你想让命令监听输入,你可以简单地设置`cmd.Stdin = os.Stdin`,从而使你好像从shell中执行了那个命令. (3认同)
  • 对于那些希望重定向到`log`而不是stdout的人,有一个答案[这里](http://stackoverflow.com/a/25191479/616644) (3认同)

rua*_*akh 18

我相信,如果导入ioos与替换此:

//fmt.Println(out)
Run Code Online (Sandbox Code Playgroud)

有了这个:

go io.Copy(os.Stdout, out)
Run Code Online (Sandbox Code Playgroud)

(见文档io.Copyos.Stdout),它会做你想要什么.(免责声明:未经测试.)

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

  • @mbert:我已经使用了足够多的其他语言,并且已经阅读了足够的关于Go的内容,以确定可能存在的功能,以及大致的形式; 然后我只需要查看相关的包文档(由谷歌搜索找到)来确认我的预感是否正确,并找到必要的细节.最难的部分是(1)找到什么标准输出(`os.Stdout`)和(2)确认前提,如果你根本不调用`cmd.StdoutPipe()`,标准输出转到`/ dev/null`而不是父进程的标准输出. (2认同)

eli*_*eve 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")
}
Run Code Online (Sandbox Code Playgroud)