Co robi `kill -0 $ pid` w skrypcie powłoki?

Odpowiedzi:

136

wysłanie sygnału 0do podanego PIDpo prostu sprawdza, czy jakiś proces z podanym PIDjest uruchomiony i masz uprawnienia do wysłania do niego sygnału.

Aby uzyskać więcej informacji, zobacz następujące strony podręcznika:

zabić (1)
$ man 1 kill
...
If sig is 0, then no signal is sent, but error checking is still performed.
...
zabić (2)
$ man 2 kill
...
If sig is 0, then no signal is sent, but error checking is still performed; this 
can be used to check for the existence of a process ID or process group ID.
...
dwalter
źródło
7
Lokalizacja tych informacji (jeśli w ogóle istnieją) jest w dużym stopniu zależna od systemu. W najnowszych systemach opartych na Debianie użyj man 2 killzamiast tego.
Todd A. Jacobs
2
Obie man 1 killi man 2 killmiałem to w moim systemie Fedora 20. Trudno to jednak zauważyć, zakopane w obu tych stronach podręcznika.
slm
Lub zamiast tego polegaj na podręczniku posix: If sig is 0 (the null signal), error checking is performed but no signal is actually sent. The null signal can be used to check the validity of pid. pubs.opengroup.org/onlinepubs/009695399/functions/kill.html
Thomas Hughes
2
Czuję, że komenda man 2 killjest poza pierwszą poprawką :)
JBaczuk 24.08.17
126

To dobre pytanie, ponieważ ...

... znalezienie dokumentacji dotyczącej tego specjalnego sygnału może być trudne. Pomimo tego, co powiedzieli inni, jedyna wzmianka o tym sygnale w man 1 killsystemach opartych na Debianie to:

Szczególnie przydatne sygnały obejmują HUP, INT, KILL, STOP, CONT i 0.

Niezbyt pomocne, zwłaszcza jeśli jeszcze nie wiesz, co robi sygnał. Nie jest również wymieniony na liście wyników programu kill -l, więc nie będziesz o tym wiedział, chyba że już o tym wiesz.

Gdzie to znaleźć udokumentowane

W systemach Debian i Ubuntu wynik polecenia man 2 killmówi po części:

Jeśli sig ma wartość 0, to żaden sygnał nie jest wysyłany, ale sprawdzanie błędów jest nadal wykonywane; można to wykorzystać do sprawdzenia istnienia identyfikatora procesu lub identyfikatora grupy procesów.

Do czego służy

Możesz użyć, kill -0aby sprawdzić, czy proces jest uruchomiony. Rozważ te przykłady.

# Kill the process if it exists and accepts signals from
# the current user.
sleep 60 &
pid=$!
kill -0 $pid && kill $pid

# Check if a PID exists. When missing, this should result
# in output similar to:
#    bash: kill: (6228) - No such process
#    Exit status: 1
kill -0 $pid; echo "Exit status: $?"

Możesz również użyć, kill -0aby określić, czy bieżący użytkownik ma uprawnienia do sygnalizowania danego procesu. Na przykład:

# See if you have permission to signal the process. If not,
# this should result in output similar to:
#     bash: kill: (15764) - Operation not permitted
#     Exit status: 1
sudo sleep 60 &
kill -0 $!; echo "Exit status: $?"
Todd A. Jacobs
źródło
Na komputerach Mac i BSD jest to również udokumentowane w kill(2) Here's the snippet:The kill() function sends the signal specified by sig to pid, a process or a group of processes. Typically, Sig will be one of the signals specified in sigaction(2). A value of 0, however, will cause error checking to be performed (with no signal being sent). This can be used to check the validity of pid.
lukecampbell
8
To powinna być akceptowana odpowiedź. O wiele lepszy niż ten drugi. dokumentacja dotycząca sygnału 0 jest trudna do zlokalizowania. Jest to zakopane na killstronie podręcznika : "Jeśli sig ma wartość 0, to żaden sygnał nie jest wysyłany, ale sprawdzanie błędów jest nadal wykonywane."
slm
6

To polecenie sprawdza, czy proces z PID w $ pid jest aktywny.

Fritz G. Mehner
źródło
1
Strona podręcznika mówi: "Jeśli sig ma wartość 0, to żaden sygnał nie jest wysyłany, ale sprawdzanie błędów jest nadal wykonywane." Do jakiego sprawdzania błędów mówimy tutaj?
gjain
2
-1, ponieważ proces z PID $pidmoże być uruchomiony, ale nie masz uprawnień do wysyłania do niego sygnału.
dwalter
2
@dwalter: Jeśli nie masz pozwolenia, otrzymasz EPERM. Jeśli nie istnieje, otrzymasz ESRCH. kill(1)Wypisze inny błąd dla każdego. Dzięki temu możesz stwierdzić, czy pid żyje, niezależnie od tego, czy masz uprawnienia do wysyłania sygnałów, czy nie. Ponadto typowym użyciem kill -0jest sprawdzenie, czy pid żyje, nawet jeśli nie zawsze jest używany poprawnie. Powiedziałbym, że ta odpowiedź jest poprawna (poza pisownią).
camh
3
@camh: no, wartość zwracana kill -0 $pidbędzie taka sama w obu przypadkach. Zwróci, 1więc nie możesz powiedzieć bez analizy wyniku, killczy proces jest uruchomiony, czy nie, jeśli nie masz uprawnień do wysyłania do niego sygnału. EDYCJA: tak, wiem, że jest używana przez większość czasu do sprawdzania, czy proces jest aktywny, ale jest to błędne, chyba że możesz zagwarantować, że masz uprawnienia do wysyłania sygnału (np: bycie rootem)
dwalter
2
@dwalter: Chodziło mi o to, że odpowiedź jest prawidłowa. Próbowałeś być pedantyczny i wskazałeś, że był inny przypadek błędu, ale mówię ci, że technicznie odpowiedź obejmuje również ten przypadek, ponieważ killwbudowany bash (pytanie jest oznaczone bash) podaje typ błędu na stderr i wskazanie błędu w kodzie powrotu. Oznacza to, że „To polecenie sprawdza [czy] istnieje proces z PID w $ pid” jest całkowicie poprawne, jeśli poprawnie zinterpretujesz dane wyjściowe. [Nie komentowałbym, gdybyś nie powiedział, że dałeś -1 do odpowiedzi. Twój komentarz jest ważny w inny sposób].
camh
6

Kill -0 $ pid służy do sprawdzenia, czy proces z pid istnieje, czy nie.

Zachowaj ostrożność podczas używania polecenia „kill -0 $ pid”, aby sprawdzić istnienie procesu, ponieważ

  1. Gdy zamierzony proces zakończy się, jego pid można przydzielić do innego nowo utworzonego procesu. (Więc nie można być tak pewnym, że dany proces jest aktywny, czy nie)

  2. W przypadku procesu Zombie, na który dziecko czeka, aż rodzic zadzwoni. Tutaj trzyma $ pid i daje pozytywny wynik, gdy ten proces nie jest uruchomiony.

Sandeep_black
źródło
1

Zabij -0 $ pid używany do sprawdzenia, czy proces działający z $ pid istnieje, czy nie. Ale może to być trudne, ponieważ identyfikator procesu można ponownie przypisać po zakończeniu procesu i uruchomieniu nowego procesu. Można użyć killall -0, aby dowiedzieć się, czy dany proces jest uruchomiony, czy nie.


źródło
0

Wysłanie EXITsygnału lub 0do procesu:

  1. Sprawdź, czy istnieje proces.
  2. Wykonaj różne sprawdzanie błędów w procesie (PID, PGID itp.).
  3. Po stdoutsukcesie nie wyśle ​​żadnych danych wyjściowych .
  4. Wyślij komunikat o błędzie do stderr jeśli coś jest nie tak.
  5. Podaj fałszywy alarm, jeśli proces nie działa (np. Zombie).

Mówiąc dokładniej, użyteczną funkcją dla twoich skryptów powłoki byłaby:

function isProcess ()
{
    kill -s EXIT $1 2> /dev/null
}

To nie zwraca żadnego tekstu w stdoutprzypadku sukcesu, ale komunikat o błędzie w stderrprzypadku niepowodzenia (ale przekierowałem ten komunikat o błędzie do/dev/null ).

Jeśli obawiasz się stanu procesu nieistniejącego / zombie , musisz użyć ps, najlepiej z --no-headersprzełącznikiem.

#!/bin/ksh

function trim ()
{
    echo -n "$1" | tr -d [:space:]
}

function getProcessStatus ()
{
    trim $(ps -p $1 -o stat --no-headers)
}

function isZombie ()
{
    typeset processStatus=$(getProcessStatus $1)

    [[ "$processStatus" == "Z" ]]
    return $?
}
Anthony Rutledge
źródło