检查exec.Cmd是否在Go中运行完毕

时间:2017-10-25 13:41:08

标签: go

我试图在这些情况下检查exec.Cmd 是否正在运行

  1. 在我实际启动命令之前
  2. 命令启动后,但在完成之前
  3. 命令完成后
  4. 如果它正在运行,这将允许我终止此命令,以便我可以使用不同的参数再次启动它。

    以下简单用例:

    c := exec.Command("omxplayer", "video.mp4")
    s, _ := c.StdinPipe() // use the pipe to send the "q" string to quit omxplayer
    
    log.Printf("Running (false): %v\n", checkRunning(c)) // prints false: command has not started yet
    c.Start()
    log.Printf("Running (true): %v\n", checkRunning(c)) // print true: command has started
    
    time.AfterFunc(3*time.Second, func() {
      log.Println("about to quit process...")
      log.Printf("Running (true): %v\n", checkRunning(c)) // prints true: command still running at this point
      s.Write([]byte("q"))
    })
    
    log.Println("waiting for command to end")
    log.Printf("Running (true): %v\n", checkRunning(c)) // prints true: command still running at this point
    c.Wait()
    log.Println("command should have ended by now")
    log.Printf("Running (false): %v\n", checkRunning(c)) // prints false: command ended at this point
    

    这是我能想到的最好的:

    func checkRunning(cmd *exec.Cmd) bool {
      if cmd == nil || cmd.ProcessState != nil && cmd.ProcessState.Exited() || cmd.Process == nil {
        return false
      }
    
      return true
    }
    

    它适用于上面的用例,但它似乎过于复杂,我不确定它有多可靠。

    有更好的方法吗?

2 个答案:

答案 0 :(得分:5)

也许在goroutine中同步运行并将结果放在您可以选择的频道上?

c := exec.Command("omxplayer", "video.mp4")
// setup pipes and such
ch := make(chan error)
go func(){
  ch <- c.Run()
}()
select{
  case err := <- ch:
    // done! check error
  case .... //timeouts, ticks or anything else
}

答案 1 :(得分:0)

对于我来说,一个与captncraig的答案略有不同的方法:

c := exec.Command("omxplayer", "video.mp4")
err := c.Start() // starts the specified command but does not wait for it to complete

// wait for the program to end in a goroutine
go func() {
  err := c.Wait()
  // logic to run once process finished. Send err in channel if necessary
}()