我正在使用 golang 啟動進程並監視輸出。該進程將運行很長時間,我需要能夠發送信號來結束它。
我有以下程式碼,在大多數情況下運行良好。但由於某些原因,進程可能沒有輸出,for迴圈會被scan()
方法阻塞,無法接收來自processfinishchan
的訊息。
是否有一個簡單的方法可以為 scan()
方法設定逾時?我嘗試了一個解決方案,在另一個goroutine 中運行scan()
,並使用另一個select 從新的goroutine 和超時通道接收,但考慮到外部for
循環,是否會有越來越多的goroutine 被scan
阻塞? p>
// code that start the process... scanner := bufio.NewScanner(stdout) for { select { case <-processFinishChan: // send to this channel to terminate the process log.Println("Killing Process") err := cmdObject.Process.Kill() if err != nil { log.Printf("Error Killing: %v", err) } else { return } default: // default case, read the output of process and send to user. if !scanner.Scan() && scanner.Err() == nil { // reach EOF return } m := scanner.Bytes() WSOutChanHolder.mu.Lock() for _, ch := range WSOutChanHolder.data { ch <- m } WSOutChanHolder.mu.Unlock() } }
假設stdout
是cmdobject.stdoutpipe()
的結果,則讀取器應在進程退出後等待時關閉讀取器並中斷任何正在進行的讀取。
wait 將在看到命令退出後關閉管道,因此大多數呼叫者不需要自行關閉管道。
所以,我們需要在一個單獨的goroutine中殺死該進程,然後在殺死該進程後等待觀察它的發生並關閉閱讀器。
// code that start the process... scanner := bufio.NewScanner(stdout) go func() { <-processFinishChan: // send to this channel to terminate the process log.Println("Killing Process") err := cmdObject.Process.Kill() if err != nil { log.Printf("Error Killing: %v", err) } cmdObject.Wait() } () for { // default case, read the output of process and send to user. if !scanner.Scan() && scanner.Err() == nil { // reach EOF return } m := scanner.Bytes() WSOutChanHolder.mu.Lock() for _, ch := range WSOutChanHolder.data { ch <- m } WSOutChanHolder.mu.Unlock() }
以上是如何為循環掃描的bufio掃描器設定逾時?的詳細內容。更多資訊請關注PHP中文網其他相關文章!