2013-03-04 9 views
12

Если у меня есть PID процесса, достаточно os.FindProcess, чтобы проверить существующий процесс? Я имею в виду, если он вернется err могу ли я предположить, что он прекращен (или убит)?Проверьте, существует ли процесс в пути

Edit:

Я только написал функцию обертки вокруг kill -s 0 (старого стиля тестирования процесса Баша). Это работает без проблем, но я до сих пор счастлив, если есть другие решения (сделано с гоу библиотек) к этой проблеме .:

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 
} 

ответ

26

Вот традиционный 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 
+0

Thats it! Спасибо за показ Go way :) –

+0

Зачем вы разбираетесь в 'int64'. Не будет ли «Atoi» лучше (нет преобразования типа в «FindProcess»)? – tjameson

+0

Да, вы правы, «Атои» будет лучше. Наверное, я использовал 'ParseInt' совсем недавно и забыл об этом! –

5

На Unix-подобных системах (Linux, FreeBSD, и т.д.) os.FindProcess будет никогда не возвращайте ошибку. Я не знаю, что происходит в Windows. Это означает, что вы не будете знать, правильный ли PID, пока вы не попытаетесь использовать * os.Process для чего-то.

Вы можете посмотреть код here.

+0

Вы правы.Он всегда дает правду, я нашел работу (смотри мое редактирование выше) –

+0

Из моего опыта работы в Windows 10 'os.FindProcess' возвращает ошибку, если процесс с заданным PID не запущен. – Kerrmiter

1

Если ранее неизвестный pid не найден в системе (не уверен в функциях go), это означает, что процесс определенно завершен и соединен (в Unix с wait call).

Но, наоборот, это не обязательно так. Просто потому, что pid существует, он не гарантирует, что это тот же процесс, что и раньше. Например, есть только 65535 действительных разрядов в стандартном Linux, и они могут быть повторно использованы, когда есть обертка. Однако, если вы достаточно часто проверяете, для практических целей вам не нужно заботиться об этом (до тех пор, пока pid неправильного нового процесса будет обнаружен не является уязвимостью безопасности или чем-то еще критическим, что кто-то может попытаться вызвать намеренно для вредоносных цели).

Ссылки по теме (и связанные с ними вопросы на их правых колонках):

+0

Хотелось бы, чтобы я мог повыситься не один раз. Наблюдение, что pids повторно используется, является критическим для всех, кто хочет надежно контролировать процессы на современном оборудовании: если что-то плохо себя ведет и возрождается, пространство имен pid будет быстро исчерпано. Поскольку идентификаторы потоков находятся в том же пространстве имен, что и идентификатор процесса, процессы с большой резьбой усугубляют проблему. – Mark

+1

Забыл упомянуть ... Если вам нужна дополнительная уверенность, убедитесь, что [время начала процесса] (http://unix.stackexchange.com/a/7871/158521) для $ pid не изменилось между чеками. Если это так, это другой процесс. Если нет, это вряд ли будет другим процессом. – Mark

+0

Что вы подразумеваете под «крайне маловероятным»? При каких обстоятельствах это могло бы не быть другим процессом? Предполагая, что процесс был жив дольше, чем одна единица, независимо от того, в каком начальном времени она измеряется (так что быстрая смерть/воссоздание с помощью ПИД-защиты не смущала контролер), единственное обстоятельство, о котором я могу думать, - это начало времени. Есть ли другие? –

2

Вы также можете использовать syscall.Kill. Это меньше кода.

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

Кроме примечания из ответа [Nick Craig-Wood] (http://stackoverflow.com/a/15210305/55504), что ошибка, отличная от нуля могут быть возвращены для существующих процессов. У вас должен быть более условный (возможно, «err == nil || err == syscall.EPERM», возможно, больше). –

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 
} 
Смежные вопросы