检查流程是否存在

时间:2013-03-04 14:44:06

标签: process go

如果我有一个进程的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
}

8 个答案:

答案 0 :(得分:29)

以下是传统的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

答案 1 :(得分:5)

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

您可以查看代码here

答案 2 :(得分:3)

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

killErr := syscall.Kill(pid, syscall.Signal(0))
procExists := killErr == nil

答案 3 :(得分:2)

如果在系统中找不到以前已知的pid(不确定go函数),则表示进程已经终止并已加入(在Unix上,wait call)。

但其他方式并不一定如此。仅仅因为存在pid,它并不保证它与以前的过程相同。例如,标准Linux中只有65535个有效的pid,并且当存在环绕时它们可以被重用。但是,如果您经常合理地检查,出于实际目的,您不需要关心这一点(只要找到错误的新进程的pid不是安全漏洞或其他关键的东西,有人可能会试图故意触发恶意目的)。

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

答案 4 :(得分: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
}

答案 5 :(得分:0)

到目前为止,所有答案都是不完整的实现。参见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
    }

答案 6 :(得分: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()

答案 7 :(得分: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