首页 >后端开发 >Golang >如何从 Go 中长时间运行的命令流式传输部分输出?

如何从 Go 中长时间运行的命令流式传输部分输出?

Mary-Kate Olsen
Mary-Kate Olsen原创
2024-12-24 00:18:15811浏览

How to Stream Partial Output from a Long-Running Command in Go?

流式传输命令输出进度

在执行长时间运行的命令并且其输出需要连续流式传输到父进程和日志文件的情况下,可以利用 cmd.StdoutPipe() 方法来捕获输出。

cmd := exec.Command("sh", "-c", "some long runnig task")

stdout, _ := cmd.StdoutPipe()
cmd.Start()

scanner := bufio.NewScanner(stdout)
for scanner.Scan() {
    m := scanner.Text()
    fmt.Println(m)
    log.Printf(m)
}

cmd.Wait()

但是,这种方法仅提供最终输出为单个字符串,而不是流式传输部分结果。

输出受限的原因

bufio.NewScanner() 函数对行进行操作,当遇到换行符时返回完整的行。如果正在执行的命令不会产生换行符,则不会立即流式传输输出。

可能的解决方法

要解决此限制,可以考虑多种方法:

  1. 按单词或字符朗读:
    通过设置使用 Scanner.Split() 的分割函数,您可以按单词或字符扫描输入,捕获生成的输出。

    scanner := bufio.NewScanner(stdout)
    scanner.Split(bufio.ScanRunes)
  2. 手动阅读:
    逐字节或逐符文读取允许您捕获生成的输出,而无需依赖换行符

    oneByte := make([]byte, 1)
    for {
        _, err := stdout.Read(oneByte)
        if err != nil {
            break
        }
        fmt.Printf("%c", oneByte[0])
    }
    
    oneRune := make([]byte, utf8.UTFMax)
    for {
        count, err := stdout.Read(oneRune)
        if err != nil {
            break
        }
        fmt.Printf("%s", oneRune[:count])
    }

注意事项

管理子进程中标准输出和错误流的缓冲区大小至关重要。默认情况下,如果不读取这些缓冲区,可能会导致子进程挂起。因此,建议始终读取 stdout 和 stderr 流。

以上是如何从 Go 中长时间运行的命令流式传输部分输出?的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn