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 ではwait callで) 参加したことを意味します。

しかし、その逆は必ずしも真実ではありません。pid が存在するからといって、以前と同じプロセスであるとは限りません。たとえば、標準の Linux では有効な pid は 65535 しかなく、ラップアラウンドがある場合に再利用できます。ただし、適度に頻繁にチェックする場合、実際にはこれを気にする必要はありません (間違った新しいプロセスの 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 に答える