检查进程是否存在

If I have the PID of a process, is os.FindProcess enough to test for the existing of the process? I mean if it returns err can I assume that it's terminated (or killed)?

Edit:

I've just wrote a wrapper function around kill -s 0 (old-style bash process testing). This works without any problem, but I'm still happy if there is other solutions (done with go libraries) to this problem.:

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
}

Here is the traditional unix way to see if a process is alive - send it a signal of 0 (like you did with your bash example).

From 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.

And translated into 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
", err)
        } else {
            err := process.Signal(syscall.Signal(0))
            fmt.Printf("process.Signal on pid %d returned: %v
", pid, err)
        }

    }
}

When you run it you get this, showing that process 123 is dead, process 1 is alive but not owned by you and process 12606 is alive and owned by you.

$ ./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

On unix like systems (linux, freebsd, etc) os.FindProcess will never return an error. I don't know what happens on Windows. This means you won't know if the PID is correct until you try to use the *os.Process for something.

You can look at the code here.

If a previously known pid is not found in the system (not sure of go functions), it means process has definitely terminated and has been joined (on Unix, with wait call) too.

But other way around is not necessarily true. Just because a pid exists, it does not quarantee it is same process as before. There are only 65535 valid pids in standard Linux for example, and they can get re-used when there is a wrap-around. However, if you check reasonably often, for practical purposes you don't need to care about this (as long as pid of wrong new process being found is not a security vulnerability or something else critical, which somebody might try to trigger intentionally for malicious purposes).

Related links (and Related questions on their right columns):

You can also just use syscall.Kill. It amounts to less code.

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

On Windows checking the result of os.FindProcess() seems to be enough to check if process is running.

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
}