首頁 >後端開發 >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