19

如果我有进程的 PID,os.FindProcess 是否足以测试进程的存在?我的意思是如果它返回err,我可以假设它被终止(或被杀死)吗?

编辑:

我刚刚围绕kill -s 0(旧式 bash 进程测试)编写了一个包装函数。这没有任何问题,但如果有其他解决方案(使用 go 库完成)来解决这个问题,我仍然很高兴。:

func checkPid(pid int) bool {
    out, err := exec.Command("kill", "-s", "0", strconv.Itoa(pid)).CombinedOutput()
    if err != nil {
        log.Println(err)
    }

    if string(out) == "" {
        return true // pid exist
    }
    return false
}
4

8 回答 8

41

这是查看进程是否处于活动状态的传统 unix 方法 - 向其发送 0 信号(就像您对 bash 示例所做的那样)。

来自kill(2)

   If  sig  is 0, then no signal is sent, but error checking is still per‐
   formed; this can be used to check for the existence of a process ID  or
   process group ID.

并翻译成 Go

package main

import (
    "fmt"
    "log"
    "os"
    "strconv"
    "syscall"
)

func main() {
    for _, p := range os.Args[1:] {
        pid, err := strconv.ParseInt(p, 10, 64)
        if err != nil {
            log.Fatal(err)
        }
        process, err := os.FindProcess(int(pid))
        if err != nil {
            fmt.Printf("Failed to find process: %s\n", err)
        } else {
            err := process.Signal(syscall.Signal(0))
            fmt.Printf("process.Signal on pid %d returned: %v\n", pid, err)
        }

    }
}

当你运行它时,你会得到这个,显示进程 123 已经死了,进程 1 是活动的但不属于你,进程 12606 是活动的并且属于你。

$ ./kill 1 $$ 123
process.Signal on pid 1 returned: operation not permitted
process.Signal on pid 12606 returned: <nil>
process.Signal on pid 123 returned: no such process
于 2013-03-04T20:16:29.520 回答
6

在类 unix 系统(linux、freebsd 等)上,os.FindProcess 永远不会返回错误。我不知道在 Windows 上会发生什么。这意味着在您尝试使用 *os.Process 之前,您不会知道 PID 是否正确。

你可以看看这里的代码。

于 2013-03-04T15:13:39.507 回答
4

您也可以只使用syscall.Kill. 它相当于更少的代码。

killErr := syscall.Kill(pid, syscall.Signal(0))
procExists := killErr == nil
于 2015-02-15T01:20:57.920 回答
2

如果在系统中未找到先前已知的 pid(不确定 go 函数),则意味着进程肯定已终止并已加入(在 Unix 上,带有等待调用)。

但反过来不一定是真的。仅仅因为存在 pid,它并不能保证它与以前的进程相同。例如,标准 Linux 中只有 65535 个有效的 pid,当有回绕时它们可以被重新使用。但是,如果您经常检查,出于实际目的,您不需要关心这一点(只要发现错误的新进程的 pid 不是安全漏洞或其他关键问题,有人可能会故意触发恶意目的)。

相关链接(以及右栏中的相关问题):

于 2013-03-04T15:21:39.663 回答
2

到目前为止,所有答案都是不完整的实现。请参阅https://github.com/shirou/gopsutil/blob/c141152a7b8f59b63e060fa8450f5cd5e7196dfb/process/process_posix.go#L73以获得更完整的实现(内联复制)

    func PidExists(pid int32) (bool, error) {
        if pid <= 0 {
            return false, fmt.Errorf("invalid pid %v", pid)
        }
        proc, err := os.FindProcess(int(pid))
        if err != nil {
            return false, err
        }
        err = proc.Signal(syscall.Signal(0))
        if err == nil {
            return true, nil
        }
        if err.Error() == "os: process already finished" {
            return false, nil
        }
        errno, ok := err.(syscall.Errno)
        if !ok {
            return false, err
        }
        switch errno {
        case syscall.ESRCH:
            return false, nil
        case syscall.EPERM:
            return true, nil
        }
        return false, err
    }
于 2019-12-23T18:16:22.157 回答
0

在 Windows 上检查结果os.FindProcess()似乎足以检查进程是否正在运行。

func isProcessRunning(pid int) bool {
    _, err = os.FindProcess(pid)
    if err != nil {
        return false
    }
    if runtime.GOOS == "windows" {
        return true
    }
    return false // further checking for other systems then Windows is not supported here
}
于 2017-06-05T11:23:53.610 回答
0

经过几个小时的搜索,知道进程是否在 Windows 上运行的正确答案如下:

func CheckProcessLife(pid int){
    cmd,_ := exec.Command("tasklist","/FI", "PID eq " + strconv.Itoa(pid)).Output()
    output := string(cmd[:])
    splitOutp := strings.Split(output, " ")
    if !(splitOutp[1] == "no") {
        time.Sleep(500 * time.Millisecond)
        fmt.Println("Process is running...")
        CheckProcessLife(pid)
    }else{
        fmt.Println("Process is no longer running.")
    }
}

您可以检查进程是使用他的 PID 还是直接使用他的名字运行,只需更改此行:

cmd,_ := exec.Command("tasklist","/FI", "IMAGENAME eq yourprocessname.exe").Output()
于 2020-03-26T20:58:50.033 回答
0

这是如何在 Windows 上使用 Golang 检查进程是否存在/运行的一种方法。

我们执行命令:

TASKLIST /V /NH /FI "PID eq 23232"

哪个可以返回:

INFO: No tasks are running which match the specified criteria.

或者如果发现:

Image Name                     PID Session Name        Session#    Mem Usage Status          User Name                                              CPU Time Window Title                                                         
========================= ======== ================ =========== ============ =============== ================================================== ============ ========================================================================
chrome.exe                   23232 Console                    1     42,472 K Unknown         THANOS\MARVEL                                       0:00:00 N/A                                         

这是一个利用这些信息的函数。

func isProcessRunning(pid int) bool {
    cmd := exec.Command("TASKLIST", "/FI", fmt.Sprintf("PID eq %d", pid))
    result, err := cmd.Output()
    if err != nil {
        return false
    }
    return !bytes.Contains(result, []byte("No tasks are running"))
}

最好的一点是您也可以通过其他参数找到该过程:

ImageName   eq, ne                  Image Name String
PID         eq, ne, gt, lt, ge, le  Process ID, A Positive integer.
Session     eq, ne, gt, lt, ge, le  Any valid session number.
SessionName eq, ne                  String
Status      eq, ne                  RUNNING | NOT RESPONDING | UNKNOWN
CPUTime     eq, ne, gt, lt, ge, le  Time hh:mm:ss
MemUsage    eq, ne, gt, lt, ge, le  Memory usage in KB, specify a valid integer.
Username    eq, ne                  User name ([Domain\]User).
Services    eq, ne                  Service Name String
Windowtitle eq, ne                  Window Title String
Modules     eq, ne                  DLL Name String
于 2021-04-24T01:04:50.980 回答