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并发读取标准输出和标准错误流,确保输出能够立即显示给用户。

回到顶部