我想找到最好的通用方法来检查进程是否存在并且是否在任何linux上运行。
在Unix / BSD中我可以通过kqueue执行此操作,这要归功于syscall.Kqueue()
使用EVFILT_PROC / NOTE_EXIT
它没有'重要的是,如果是mac os X,netbsd,freebsd等,代码将正常工作,并有助于监控PID的状态。
试图在linux上实现相同的目标,我想到了定期检查/proc/[pid]/stat
文件是否存在的想法,而不是像这里建议的那样发送信号0,kill -s 0
:{{3主要是为了简化逻辑,因为可以为现有进程返回非零错误。
可能使用类似的东西:
initialStat, err := os.Stat(fmt.Sprintf("/proc/%d/stat", self.pid)
if err != nil {
return
}
for {
stat, err := os.Stat(fmt.Sprintf("/proc/%d/stat", self.pid)
if err != nil {
return err
}
if stat.Size() != initialStat.Size() || stat.ModTime() != initialStat.ModTime() {
return nil
}
// wondering how to avoid sleeping here
time.Sleep(time.Second)
}
但是想知道在所有linux /proc/[pid]/stat
中是否总是可用或者通过发送信号0 kill -0 $PID
基本上做同样的事情。
最后,我总是可以回退到kill -O $PID
,但只是想知道可以使用哪些可行的解决方案(可能是inotify),目的是避免在循环中睡眠,主要是为了不消耗大量的CPU资源。 / p>
答案 0 :(得分:0)
对于子进程,您应该使用waitpid
。
可以使用适用于您的案例的流程事件(http://netsplit.com/the-proc-connector-and-socket-filters)的netlink API:
http://godoc.org/github.com/cloudfoundry/gosigar/psnotify#PROC_EVENT_EXIT
import "github.com/cloudfoundry/gosigar/psnotify"
func waitpid(pid int) error {
watcher, err := psnotify.NewWatcher()
if err != nil {
return err
}
if err := watcher.Watch(pid, psnotify.PROC_EVENT_EXIT); err != nil {
return err
}
defer watcher.Close()
// At this point, you should probably syscall.Kill(pid, 0) to check that the process is still running.
for {
select {
case ev := <-watcher.Error:
// TODO..
return ev
case <-watcher.Exit:
return nil
}
}
}