在执行长时间运行的命令并且其输出需要连续流式传输到父进程和日志文件的情况下,可以利用 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() 函数对行进行操作,当遇到换行符时返回完整的行。如果正在执行的命令不会产生换行符,则不会立即流式传输输出。
要解决此限制,可以考虑多种方法:
按单词或字符朗读:
通过设置使用 Scanner.Split() 的分割函数,您可以按单词或字符扫描输入,捕获生成的输出。
scanner := bufio.NewScanner(stdout) scanner.Split(bufio.ScanRunes)
手动阅读:
逐字节或逐符文读取允许您捕获生成的输出,而无需依赖换行符
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中文网其他相关文章!