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

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

The variable out is of type io.ReadCloser and I don't know what I should do with it to achieve my task, and I can't find anything helpful on the web on this topic.

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

Explanation to the code: uncomment the Println function to get the code to compile, I know that Println(out io.ReadCloser) is not a meaningful function.
(它生成输出 &{3 |0 <nil> 0})只需要这两行代码就可以进行编译。

53516 次浏览

我相信,如果你导入 ioos并替换这个:

//fmt.Println(out)

用这个:

go io.Copy(os.Stdout, out)

(参见文档 io.Copy对于 os.Stdout) ,它将做你想要的。(免责声明: 未经测试。)

By the way, you'll probably want to capture standard-error as well, by using the same approach as for standard-output, but with cmd.StderrPipe and os.Stderr.

对于那些不需要在循环中执行此操作,但希望命令输出在不阻塞其他语句的情况下回送到终端的用户:

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

Now I want to have the stdout of the child program in my terminal 开始家长程序的窗口。

没有必要搞乱管道或者高级程序,这个很简单。

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