dongliu8559
2019-08-02 19:32
浏览 155
已采纳

如何检查在后台启动的进程是否仍在运行?

It looks like if you create a subprocess via exec.Cmd and Start() it, the Cmd.Process field is populated right away, however Cmd.ProcessState field remains nil until the process exits.

   // ProcessState contains information about an exited process,
   // available after a call to Wait or Run.
   ProcessState *os.ProcessState

So it looks like I can't actually check the status of a process I Start()ed while it's still running?

It makes no sense to me ProcessState is set when the process exits. There's an ProcessState.Exited() method which will always return true in this case.


So I tried to go this route instead: cmd.Process.Pid field exists right after I cmd.Start(), however it looks like os.Process doesn't expose any mechanisms to check if the process is running.

os.FindProcess says:

On Unix systems, FindProcess always succeeds and returns a Process for the given pid, regardless of whether the process exists.

which isn't useful –and it seems like there's no way to go from os.Process to an os.ProcessState unless you .Wait() which defeats the whole purpose (I want to know if the process is running or not before it has exited).

图片转代码服务由CSDN问答提供 功能建议

如果您通过 exec.Cmd 启动()它,将立即填充 Cmd.Process 字段,但是 Cmd.ProcessState 字段仍为 nil 直到进程退出。

  // ProcessState包含有关已退出进程的信息,
 //在调用Wait或Run之后可用。
 ProcessState  * os.ProcessState 
   
  
 
 

所以看来我实际上无法检查我的 Start()< / code> ed仍在运行?

对于我来说,在进程退出时设置 ProcessState 毫无意义。 有一个 ProcessState.Exited()方法,该方法将始终返回 true < / code>。


所以我改走了这条路线: cmd.Process.Pid 字段紧随其后 我 cmd.Start(),但是它看起来像 os.Process 没有公开任何机制来检查进程是否正在运行。

os.FindProcess 说:

在Unix系统上,FindProcess总是成功并为给定的pid返回一个Process,无论该进程是否 存在。

这没用–似乎没有办法从 os.Process os.ProcessState ,除非您 .Wait()违反了整个目的(我想知道该进程是否正在运行,然后再退出)。

  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

1条回答 默认 最新

  • doujie4050 2019-08-02 21:16
    已采纳

    I think you have two reasonable options here:

    • Spin off a goroutine that waits for the process to exit. When the wait is done, you know the process exited. (Positive: pretty easy to code correctly; negative: you dedicate an OS thread to waiting.)

    • Use syscall.Wait4() on the published Pid. A Wait4 with syscall.WNOHANG set returns immediately, filling in the status.

    It might be nice if there were an exported os or cmd function that did the Wait4 for you and filled in the ProcessState. You could supply WNOHANG or not, as you see fit. But there isn't.


    The point of ProcessState.Exited() is to distinguish between all the various possibilities, including:

    • process exited normally (with a status byte)
    • process died due to receiving an unhandled signal

    See the stringer for ProcessState. Note that there are more possibilities than these two ... only there seems to be no way to get the others into a ProcessState. The only calls to syscall.Wait seem to be:

    • syscall/exec_unix.go: after a failed exec, to collect zombies before returning an error; and
    • os/exec_unix.go: after a call to p.blockUntilWaitable().

    If it were not for the blockUntilWaitable, the exec_unix.go implementation variant for wait() could call syscall.Wait4 with syscall.WNOHANG, but blockUntilWaitable itself ensures that this is pointless (and the goal of this particular wait is to wait for exit anyway).

    已采纳该答案
    打赏 评论

相关推荐 更多相似问题