簡體   English   中英

以go方式檢查進程是否存在

[英]Check if a process exists in go way

如果我有進程的 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
}

這是查看進程是否處於活動狀態的傳統 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

在類 Unix 系統(linux、freebsd 等)上,os.FindProcess 永遠不會返回錯誤。 我不知道在 Windows 上會發生什么。 這意味着在您嘗試使用 *os.Process 之前,您不會知道 PID 是否正確。

您可以在此處查看代碼。

您也可以只使用syscall.Kill 它相當於更少的代碼。

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

如果在系統中找不到先前已知的 pid(不確定 go 函數),則意味着進程肯定已終止並已加入(在 Unix 上,使用wait call )。

但其他方式不一定正確。 僅僅因為 pid 存在,它並不能保證它與以前的過程相同。 例如,在標准 Linux 中只有 65535 個有效的 pid,當有回繞時它們可以被重用。 但是,如果您經常檢查,出於實際目的,您不需要關心這一點(只要發現錯誤的新進程的 pid 不是安全漏洞或其他關鍵的東西,有人可能會試圖故意觸發惡意目的)。

相關鏈接(及其右欄中的相關問題):

到目前為止所有的答案都是不完整的實現。 請參閱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
    }

在 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
}

經過幾個小時的搜索,了解進程是否在 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()

這是如何檢查進程是否存在/在 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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM