Golang如何实时显示命令输出
Golang如何实时显示命令输出
我正在通过Go语言运行一个Linux bash脚本命令。
我想实时显示该命令的输出,该如何实现?
例如,
我通过Go语言运行 yum -y update,我想向用户实时显示其输出。
实际上,我正在开发一个在命令行中运行的软件。所以我希望向用户实时显示bash脚本的输出。
请告诉我如何实现,我阅读了许多论坛但没有理解。
他们都给出了复杂的解释。
假设我想运行:
curl -Lso- bench.sh | bash
通过Go语言运行此命令,我该如何运行以及如何向用户显示其实时输出?
2 回复
这并非一个确切的答案,但根据我搜索标准输入/输出缓冲相关的一些发现,我认为这实际上做起来很复杂。我猜写入管道与写入终端在根本上就不同。如果你找一个叫 stdbuf 的工具,或许会有些帮助。
更多关于Golang如何实时显示命令输出的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
在Go中实时显示命令输出可以通过os/exec包实现,结合io.Reader和goroutine。以下是具体实现方法:
package main
import (
"bufio"
"fmt"
"io"
"os"
"os/exec"
)
func main() {
// 创建命令
cmd := exec.Command("bash", "-c", "curl -Lso- bench.sh | bash")
// 获取标准输出管道
stdout, err := cmd.StdoutPipe()
if err != nil {
fmt.Printf("创建输出管道失败: %v\n", err)
return
}
// 获取标准错误管道
stderr, err := cmd.StderrPipe()
if err != nil {
fmt.Printf("创建错误管道失败: %v\n", err)
return
}
// 启动命令
if err := cmd.Start(); err != nil {
fmt.Printf("启动命令失败: %v\n", err)
return
}
// 创建goroutine实时读取标准输出
go func() {
scanner := bufio.NewScanner(stdout)
for scanner.Scan() {
fmt.Println(scanner.Text())
}
}()
// 创建goroutine实时读取标准错误
go func() {
scanner := bufio.NewScanner(stderr)
for scanner.Scan() {
fmt.Fprintln(os.Stderr, scanner.Text())
}
}()
// 等待命令执行完成
if err := cmd.Wait(); err != nil {
fmt.Printf("命令执行失败: %v\n", err)
}
}
对于yum -y update命令,实现方式类似:
package main
import (
"bufio"
"fmt"
"io"
"os"
"os/exec"
)
func main() {
cmd := exec.Command("yum", "-y", "update")
stdout, err := cmd.StdoutPipe()
if err != nil {
fmt.Printf("错误: %v\n", err)
return
}
stderr, err := cmd.StderrPipe()
if err != nil {
fmt.Printf("错误: %v\n", err)
return
}
if err := cmd.Start(); err != nil {
fmt.Printf("启动失败: %v\n", err)
return
}
// 实时输出标准输出
go func() {
reader := bufio.NewReader(stdout)
for {
line, err := reader.ReadString('\n')
if err != nil {
if err == io.EOF {
break
}
fmt.Printf("读取输出错误: %v\n", err)
return
}
fmt.Print(line)
}
}()
// 实时输出标准错误
go func() {
reader := bufio.NewReader(stderr)
for {
line, err := reader.ReadString('\n')
if err != nil {
if err == io.EOF {
break
}
fmt.Printf("读取错误输出错误: %v\n", err)
return
}
fmt.Fprint(os.Stderr, line)
}
}()
if err := cmd.Wait(); err != nil {
fmt.Printf("命令执行错误: %v\n", err)
}
}
如果需要同时处理输入,可以使用以下更完整的示例:
package main
import (
"bufio"
"fmt"
"io"
"os"
"os/exec"
"sync"
)
func streamOutput(reader io.Reader, wg *sync.WaitGroup, isError bool) {
defer wg.Done()
scanner := bufio.NewScanner(reader)
for scanner.Scan() {
line := scanner.Text()
if isError {
fmt.Fprintln(os.Stderr, line)
} else {
fmt.Println(line)
}
}
}
func main() {
cmd := exec.Command("bash", "-c", "curl -Lso- bench.sh | bash")
stdout, _ := cmd.StdoutPipe()
stderr, _ := cmd.StderrPipe()
cmd.Start()
var wg sync.WaitGroup
wg.Add(2)
go streamOutput(stdout, &wg, false)
go streamOutput(stderr, &wg, true)
wg.Wait()
cmd.Wait()
}
这些示例都实现了命令输出的实时显示,通过goroutine并发读取标准输出和标准错误流,确保输出能够立即显示给用户。

