2016-05-22 65 views
2

我想在goroutine中持續觸發ps命令來監視mem和cpu用法。我沒有使用top,因爲top不允許我選擇列爲ps。這個goroutine需要收到一個停止信號來停止command,但是我不知道如何在等待信號時阻止運行命令。對於top我可以這樣做:前往:在不阻止操作的情況下操作信號

top := exec.Command("top") 
<-stop // blocking 
top.Process.Signal(os.Kill) 

ps如果我這樣做:

ps := exec.Command("ps") 
for { 
    ps.Run() 
    <-stop 
} 

上面的代碼將阻塞stop。我想繼續射擊ps.Run(),同時能夠在停止信號準備就緒時停止。謝謝。

回答

1

你可以做到這一點的一種方法是利用for/select超時習語,有幾種類似的方法可以做到這一點。拿這個簡單的例子:

package main 

import (
    "fmt" 
    "time" 
) 

func main() { 
    abort := make(chan struct{}) 

    go func() { 
     for { 
      select { 
      case <-abort: 
       return 
      case <-time.After(1 * time.Second): 
       // replace fmt.Println() with the command you wish to run 
       fmt.Println("tick") 
      } 
     } 
    }() 
    // replace time.Sleep() with code waiting for 'abort' command input 
    time.Sleep(10 * time.Second) 
    abort <- struct{}{} 
} 

。如果沒有其他情況修改這個例子中你的情況的地方工作要在<-time.After():情況下,(在這種情況下),將每秒運行一次運行代碼,可以在那段時間內收到。而不是我最後放置的time.Sleep(),把代碼,將中斷<-time.After():的情況下,發送<- struct{}{}abort頻道(或任何你的名字)。

注:在此答案我不得不放棄作爲chan bool的早期版本,因爲我喜歡的<-abort true清晰度和不考慮chan struct{}是那樣清晰,我選擇不過來改變它在這個例子中,<- struct{}{}並不清楚,特別是一旦你習慣了這種模式。另外,如果你想要在for循環的每次迭代中執行該命令,而不是等待超時,那麼你可以使這種情況變成default:,刪除,並且它將在循環的每個迭代中運行,其中另一個通道是沒有準備好接收。

如果您願意,可以使用playground中的示例進行操作,雖然它不允許系統調用或在該環境中運行default:案例。

1

遍地運行它,不睡覺:

func run(stop <-chan struct{}) { 
    ps := exec.Command("ps") 
    for { 
     select { 
     case <-stop: 
      return 
     default: 
      ps.Run() 
      //processing the output 
     } 
    } 
} 

然後go run(stop)。並且每隔3秒運行一次(例如):

func run(stop <-chan struct{}) { 
    ps := exec.Command("ps") 
    tk := time.Tick(time.Second * 3) 
    for { 
     select { 
     case <-stop: 
      return 
     case <-tk: 
      ps.Run() 
      //processing the output 
     } 
    } 
} 
相關問題