为了账号安全,请及时绑定邮箱和手机立即绑定

如何以内存安全的方式获取前台应用程序的 pid?

如何以内存安全的方式获取前台应用程序的 pid?

Go
largeQ 2022-07-11 16:45:30
我想获得前台应用程序的 pid。请不要推荐robotgo,我已经尝试过并且知道它可以工作,但是正如我对问题的评论那样会导致内存泄漏。就像那里提到的代码一样,我想在循环中获取一个 pid,所以它应该是内存安全的。
查看完整描述

2 回答

?
杨魅力

TA贡献1811条经验 获得超6个赞

如果我正确理解您的问题,我认为以下程序应该会有所帮助。我正在使用该mitchellh/go-ps软件包。


package main


import (

    "flag"

    "fmt"

    "os"

    "os/exec"

    "strconv"

    "strings"

    "time"


    ps "github.com/mitchellh/go-ps"

)


func foreground(pid int) (bool, error) {

    out, err := exec.Command("/bin/ps", "-o", "stat=", "-p", strconv.Itoa(int(pid))).Output()

    if err != nil {

        return false, err

    }

    return strings.IndexByte(string(out), '+') != -1, nil

}


func getProcs() error {

    procs, err := ps.Processes()

    if err != nil {

        return err

    }

    for _, p := range procs {

        ok, err := foreground(p.Pid())

        if err != nil {

            fmt.Fprintf(os.Stderr, "error: %v\n", err)

            continue

        }

        if ok {

            fmt.Fprintf(os.Stdout, "pid: %d, process: %s\n", p.Pid(), p.Executable())

        }

    }

    return nil

}


func scheduler(tick chan<- struct{}, every time.Duration) {

    tick <- struct{}{}

    for range time.Tick(every * time.Second) {

        tick <- struct{}{}

    }

}


func main() {

    dur := flag.Duration("every", 10, "interval (in seconds)")

    flag.Parse()

    if *dur <= 0 {

        fmt.Fprintf(os.Stderr, "interval should be more than 0")

        os.Exit(1)

    }

    tick := make(chan struct{})

    go scheduler(tick, *dur)

    for range tick {

        if err := getProcs(); err != nil {

            fmt.Fprintf(os.Stderr, "error: %v\n", err)

        }

    }

}

更新:


我已经更新了答案。现在您可以打印在前台运行的进程。由于基于 darwin 的操作系统中 procfs 不可用,我们依赖于ps. 因此,如果进程在前台运行,使用ps -o stat= -p $PID会给我们一个信号。+因此,前台进程背后的理论是process's group id == controlling tty process's group id.


查看完整回答
反对 回复 2022-07-11
?
江户川乱折腾

TA贡献1851条经验 获得超5个赞

package main


import (

    "flag"

    "fmt"

    "os"

    "time"


    ps "github.com/shirou/gopsutil/process"

)


func getProcs() error {

    procs, err := ps.Processes()

    if err != nil {

        return err

    }

    for _, p := range procs {

        name, _ := p.Name()

        foreground, _ := p.Foreground()

        fmt.Fprintf(os.Stdout, "pid: %d,\tprocess: %s ,\tForeground: %v\n", p.Pid, name, foreground)

    }

    return nil

}


func main() {

    for range time.Tick(1 * time.Second) {

        if err := getProcs(); err != nil {

            fmt.Fprintf(os.Stderr, "error: %v\n", err)

        }

    }

}

它基于 shmsr 的回答,但不同的库为进程提供更多信息


查看完整回答
反对 回复 2022-07-11
  • 2 回答
  • 0 关注
  • 117 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号