我想在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()
,同时能够在停止信号准备就绪时停止。感谢。
答案 0 :(得分: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:
,删除<-time.After()
并在每次迭代时运行另一个频道未准备接收的循环。
如果您愿意,可以在playground中使用此示例,尽管它不允许系统调用,或default:
案例在该环境中运行。
答案 1 :(得分: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
}
}
}