英文:
Redirect stdout pipe of child process in Go
问题
我正在使用Go编写一个执行类似服务器程序的程序(也是Go语言)。现在我想要在启动父程序的终端窗口中获取子程序的标准输出(stdout)。一种方法是使用cmd.Output()
函数,但是这个函数只会在进程退出后才打印stdout。(这是个问题,因为这个类似服务器的程序运行时间很长,我想要读取日志输出)
变量out
的类型是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()
}
代码解释:取消注释Println
函数以使代码编译通过,我知道Println(out io.ReadCloser)
不是一个有意义的函数。(它会输出&{3 |0 <nil> 0}
)这两行只是为了让代码能够编译通过。
英文:
I'm writing a program in Go that executes a server like program (also Go). Now I want to have the stdout of the child program in my terminal window where I started the parent program. One way to do this is with the cmd.Output()
function, but this prints the stdout only after the process has exited. (That's a problem because this server-like program runs for a long time and I want to read the log 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.
(it produces the output &{3 |0 <nil> 0}
) These two lines are just required to get the code to compile.
答案1
得分: 229
现在我想要在启动父程序的终端窗口中看到子程序的标准输出,不需要使用管道或者goroutines,这个很简单。
func main() {
// 将`ls`(以及它的参数)替换为更有趣的内容
cmd := exec.Command("ls", "-l")
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Run()
}
英文:
> Now I want to have the stdout of the child program in my terminal
> window where I started the parent program.
No need to mess with pipes or goroutines, this one is easy.
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()
}
答案2
得分: 21
我相信如果你导入io
和os
并将这段代码替换为:
//fmt.Println(out)
使用以下代码:
go io.Copy(os.Stdout, out)
(参见io.Copy的文档和os.Stdout的文档),它将实现你想要的功能。(免责声明:未经测试。)
顺便说一下,你可能还想捕获标准错误输出,可以使用与标准输出相同的方法,但使用cmd.StderrPipe
和os.Stderr
。
英文:
I believe that if you import io
and os
and replace this:
//fmt.Println(out)
with this:
go io.Copy(os.Stdout, out)
(see documentation for io.Copy
and for os.Stdout
), it will do what you want. (Disclaimer: not tested.)
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
.
答案3
得分: 15
对于那些不需要在循环中使用的人,但希望命令输出在终端中回显而不阻塞其他语句的人:
package main
import (
"fmt"
"io"
"log"
"os"
"os/exec"
)
func checkError(err error) {
if err != nil {
log.Fatalf("错误:%s", err)
}
}
func main() {
// 用更有趣的内容替换`ls`(及其参数)
cmd := exec.Command("ls", "-l")
// 创建类型为io.Reader的stdout、stderr流
stdout, err := cmd.StdoutPipe()
checkError(err)
stderr, err := cmd.StderrPipe()
checkError(err)
// 启动命令
err = cmd.Start()
checkError(err)
// 在我们的命令完成运行之前,不要让main()退出
defer cmd.Wait() // 不阻塞
// 非阻塞地将命令输出回显到终端
go io.Copy(os.Stdout, stdout)
go io.Copy(os.Stderr, stderr)
// 我喜欢Go的简单并发 :-D
fmt.Printf("在这里做其他事情!不需要等待。\n\n")
}
英文:
For those who don't need this in a loop, but would like the command output to echo into the terminal without having cmd.Wait()
blocking other statements:
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")
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论