亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

可靠地捕獲外部命令的輸出

可靠地捕獲外部命令的輸出

Go
守候你守候我 2022-05-18 13:50:58
我需要快速連續地調用許多短期(有時是一些長期存在的)外部流程,stdout并stderr實時處理。我已經找到了許多解決方案,使用StdoutPipe和for each,打包到 goroutines 中。這在大多數情況下都有效,但偶爾會吞下外部命令的輸出,我不知道為什么。StderrPipebufio.Scanner這是一個在 MacOS X (Mojave) 和 Linux 上顯示該行為的最小示例:package mainimport (    "bufio"    "log"    "os/exec"    "sync")func main() {    for i := 0; i < 50000; i++ {        log.Println("Loop")        var wg sync.WaitGroup        cmd := exec.Command("echo", "1")        stdout, err := cmd.StdoutPipe()        if err != nil {            panic(err)        }        cmd.Start()        stdoutScanner := bufio.NewScanner(stdout)        stdoutScanner.Split(bufio.ScanLines)        wg.Add(1)        go func() {            for stdoutScanner.Scan() {                line := stdoutScanner.Text()                log.Printf("[stdout] %s\n", line)            }            wg.Done()        }()        cmd.Wait()        wg.Wait()    }}我已經省略了stderr對此的處理。運行此程序時,我只得到大約 49,900[stdout] 1行(實際數量因每次運行而異),但應該有 50,000 行。我看到了 50,000loop行,所以它似乎不會過早死亡。這聞起來像是某處的比賽條件,但我不知道在哪里。如果我不將掃描循環放在 goroutine 中,它工作得很好,但是我失去了同時讀取的能力stderr,這是我需要的。我試過用 運行它-race,Go 報告沒有數據競爭。我沒有想法,我哪里錯了?
查看完整描述

1 回答

?
茅侃侃

TA貢獻1842條經驗 獲得超21個贊

您沒有在多個地方檢查錯誤。


在某些情況下,這實際上并沒有引起問題,但檢查一下仍然是個好主意:


cmd.Start()

可能會返回錯誤,在這種情況下該命令從未運行過。(這不是實際問題。)


stdoutScanner.Scan()返回 false 時,可能stdoutScanner.Err()會顯示錯誤。如果你開始檢查這個,你會發現一些錯誤:


2020/02/19 15:38:17 [stdout err] read |0: file already closed

這不是真正的問題,但是——啊哈——這與您看到的癥狀相符:并非所有輸出都被看到?,F在,為什么閱讀會stdout聲稱文件已關閉?嗯,stdout從哪里來的?它來自這里:


stdout, err := cmd.StdoutPipe()

看看這個函數的源代碼,它以以下幾行結尾:


c.closeAfterStart = append(c.closeAfterStart, pw)

c.closeAfterWait = append(c.closeAfterWait, pr)

return pr, nil

(并且pr是管道讀取的返回值)。嗯:什么closeAfterWait意思?


現在,這是循環中的最后兩行:


cmd.Wait()

wg.Wait()

也就是說,首先我們等待cmd完成。(cmd完成后,什么會關閉?)然后我們等待正在讀取cmd標準輸出的 goroutine 完成。(嗯,還有什么可以從pr管道中讀取?)


修復現在很明顯:將wg.Wait()等待 stdout 管道的使用者完成讀取它的 與cmd.Wait()等待echo ...退出然后關閉管道的讀取端的 交換。如果您在讀者仍在閱讀時關閉,他們可能永遠不會閱讀您所期望的內容。


查看完整回答
反對 回復 2022-05-18
  • 1 回答
  • 0 關注
  • 107 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號