Go:在不阻止操作的情况下执行信号

时间:2016-05-22 19:34:40

标签: go

我想在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(),同时能够在停止信号准备就绪时停止。感谢。

2 个答案:

答案 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
        }
    }
}