在執行長時間運行的命令並且其輸出需要連續流式傳輸到父進程和日誌檔案的情況下,可以利用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中文網其他相關文章!