2016-05-22 3 views
0

私のgoプログラムでは、特定のプロセスを継続的に監視するためにtopを実行する必要があります。しかし、topは、各行が記録された時のタイムスタンプを私に与えません。私は出力に私の自己をそれを付加考えている:Go:トップからの出力にコンテンツを追加する

top := exec.Command("top", "-p", pid) 
r, w := os.Pipe() 
top.Stdout = w 
top.Start() 

この方法で私はパイプの一端にrからの出力を読み取ることができます。 top.Stdoutから新しい行があるときに、現在のタイムスタンプを取得して出力に追加するアクションをどのように起動できますか?私はそれがコールバックやPythonのジェネレータのようにすべきだと思いますが、私はGoでそれを行う方法がわかりません。線に沿って

答えて

1

何か:

func main() { 
    for ln := range topMon(2543) { 
     fmt.Println(time.Now().UTC().Format(time.RFC3339), ln) 
    } 
} 

func topMon(pids ...int) <-chan string { 
    ch := make(chan string, 1) 
    top := exec.Command("top", "-b") 
    for _, pid := range pids { 
     top.Args = append(top.Args, "-p", strconv.Itoa(pid)) 
    } 
    r, w, _ := os.Pipe() 
    go func() { 
     sc := bufio.NewScanner(r) 
     for sc.Scan() { 
      ch <- sc.Text() 
     } 
     close(ch) 
    }() 
    top.Stdout = w 
    top.Stderr = os.Stderr 
    if err := top.Start(); err != nil { 
     panic(err) 
    } 
    return ch 
} 

チャネルの使用は一例であり、あなただけの直接パイプからrwaderを返すことができます。

+0

ゴルーチン内の 'for'ループは永遠に走っているようですね?もし私が 'top.Process.Signal(os.Kill)'を持っていたら、それに応じてそのゴルーチンを止める方法は?ありがとう。 –

+0

@JFreebird 'sc.Scan()'は、リーダが 'io.EOF'を返して終了するので、falseを返します。 – OneOfOne

関連する問題