Co robi `kill -0`?

61

Ostatnio natknąłem się na to w skrypcie powłoki.

if ! kill -0 $(cat /path/to/file.pid); then
    ... do something ...
fi

Co ma kill -0 ...zrobić?

slm
źródło
2
Zobacz tutaj, jeśli masz wątpliwości co do różnic między trappoleceniem Basha a 0 w stosunku do sygnału 0 z kill: Co to jest sygnał 0 w poleceniu pułapki?
slm
Zobacz także starsze pytanie StackOverflow Co robi kill -0 $pidskrypt powłoki? oraz Co właściwie robi kill 0? .
Adam Katz

Odpowiedzi:

76

Ten jest trochę trudny do zdobycia, ale jeśli spojrzysz na następujące 2 strony podręcznika, zobaczysz następujące uwagi:

kill (1)
$ man 1 kill
...
If sig is 0, then no signal is sent, but error checking is still performed.
...
zabij (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.
...

Zatem sygnał 0 w rzeczywistości nie wyśle ​​niczego do PID twojego procesu, ale sprawdzi, czy masz do tego uprawnienia.

Gdzie może to być przydatne?

Jednym oczywistym miejscem byłoby, gdybyś próbował ustalić, czy masz uprawnienia do wysyłania sygnałów przez uruchomiony proces kill. Możesz sprawdzić przed wysłaniem właściwego killsygnału, owijając czek, aby upewnić się, że kill -0 <PID>był on najpierw dozwolony.

Przykład

Załóżmy, że proces był uruchamiany przez użytkownika root w następujący sposób:

$ sudo sleep 2500 &
[1] 15693

Teraz w innym oknie, jeśli uruchomimy to polecenie, możemy potwierdzić, że działa PID.

$ pgrep sleep
15693

Spróbujmy teraz tego polecenia, aby sprawdzić, czy mamy dostęp do wysyłania sygnałów PID za pośrednictwem kill.

$ if ! kill -0 $(pgrep sleep); then echo "You're weak!"; fi
bash: kill: (15693) - Operation not permitted
You're weak!

Więc to działa, ale wynik przecieka komunikat z killpolecenia, że ​​nie mamy uprawnień. Nic wielkiego, po prostu złap STDERR i wyślij go na adres /dev/null.

$ if ! kill -0 $(pgrep sleep) 2>/dev/null; then echo "You're weak!"; fi
You're weak!

Kompletny przykład

Więc moglibyśmy zrobić coś takiego killer.bash:

#!/bin/bash

PID=$(pgrep sleep)
if ! kill -0 $PID 2>/dev/null; then 
  echo "you don't have permissions to kill PID:$PID"
  exit 1
fi

kill -9 $PID

Teraz, gdy uruchomię powyższe jako użytkownik inny niż root:

$ ~/killer.bash 
you don't have permissions to kill PID:15693

$ echo $?
1

Jednak gdy jest uruchamiany jako root:

$ sudo ~/killer.bash 

$ echo $?
0

$ pgrep sleep
$
slm
źródło
9
Dodałbym również, że można tego użyć w skryptach wieloprocesowych, aby sprawdzić, czy proces jest nadal aktywny.
prateek61
1
@slm nice find. Używam teraz tej logiki w skrypcie, który piszę, dzięki.
111 ---
12
Prateek61 ma rację. Nie możesz używać pgrep, psparsować ani test -e /proc/$PIDw przenośnych skryptach, ale kill -0działa wszędzie. Jeśli otrzymasz identyfikator PID, który może być nieaktualny - np. /var/runWpis - jest to przenośny sposób sprawdzenia, czy proces nadal trwa.
Warren Young,
1
Oprócz informowania Cię, czy PID żyje, skutecznie informuje również, czy nadal uruchamia proces z Twojego UID, ponieważ nie masz uprawnień do wysyłania sygnałów do innych UID (chyba że jesteś rootem). To sprawia, że ​​wyniki fałszywie dodatnie z powodu ponownego użycia PID są mniej prawdopodobne.
Barmar
Niepowodzenie kill -0 $(pgrep sleep)może niekoniecznie oznaczać , że jesteś słaby , zwróci fałsz, jeśli nie sleepuruchomi się żadna komenda, lub jeśli jest więcej niż jedna i jest jedna, której nie możesz zabić, lub jeśli jeden ze snów umrze między pgrep a zabiciem uruchamiane polecenia.
Stéphane Chazelas
22

kill -0(lub jego bardziej przenośny wariant POSIX kill -s 0) przechodzi przez proces wysyłania sygnału, ale tak naprawdę go nie wysyła. Jest to funkcja bazowego C API, którą polecenie powłoki ujawnia w prosty sposób.

kill -s 0 -- "$pid"testuje zatem, czy istnieje uruchomiony proces z danym PID (lub PGID, jeśli $pidjest ujemny) i czy bieżący proces będzie miał pozwolenie na wysłanie (dowolnego z procesów w grupie procesów w przypadku ujemnej $pid) sygnału. Jest to głównie sposób na sprawdzenie, czy proces (lub grupa procesów) żyje.

Należy pamiętać, że nawet jeśli jest uruchomiony proces z oczekiwanym PID i uprawnieniami, niekoniecznie jest to oczekiwany proces. Możliwe, że proces, którego się spodziewasz, umarł wcześniej, a jego PID został ponownie wykorzystany do niezwiązanego procesu. Właściwy sposób monitorowania procesów polega na tym, że pozwala to ich rodzicowi - PID procesu nie jest ponownie wykorzystywany, dopóki jego rodzic nie potwierdzi śmierci (dlatego istnieją zombie ), więc rodzic procesu może niezawodnie zidentyfikować swoje dzieci na podstawie ich PID.

Gilles
źródło
0

kill -0 $pidInformuje, czy z procesem $pidistnieje.

We fragmencie

if ! kill -0 $(cat /path/to/file.pid); then
    ... do something ...
fi

blok ... do something ...jest wykonywany, jeśli proces z przechowywanym PID /path/to/file.pidjest uruchomiony - i - o ile fragment kodu nie działa jako root - jeśli PID działa z tym samym użytkownikiem.

Standard POSIX określa rolę 0sygnału:

Jeśli sig wynosi 0 (sygnał zerowy), sprawdzanie błędów jest wykonywane, ale w rzeczywistości żaden sygnał nie jest wysyłany. Sygnał zerowy może być użyty do sprawdzenia ważności pid.

(kill (3p), POSIX.1-2008 - podobne sformułowanie w POSIX.1-2001)

Zauważ, że POSIX określa oba style kill -0i kill -s 0style wiersza poleceń (kill (1p)).

W przeciwieństwie do interfejsu kill syscall, killpolecenia nie można użyć do wiarygodnego sprawdzenia istnienia PIDów należących do innych użytkowników (jako zwykły użytkownik), np .:

$ kill -0 123
kill: kill 123 failed: no such process
$ echo $?
1

vs.

$ kill -0 1
kill: kill 1 failed: operation not permitted
$ echo $?
1

Podczas wywoływania funkcji kill syscall można niezawodnie rozróżnić te przypadki, patrząc na errnowartość (por. Np. Przykład w języku Python ).

maxschlepzig
źródło