Ce face `kill -0`? (Unix, Shell, Proces, Kill)

slm a intrebat.
a intrebat.

Recent am dat peste acest lucru într-un script shell.

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

Ce face kill -0 ... face?

Comentarii

  • Vedeți aici dacă sunteți confuz în legătură cu diferențele dintre Bash și Bash’s trap și 0 vs. un semnal 0 de la kill: Ce este semnalul 0 într-o comandă trap? –  > Por slm.
  • Vezi și întrebarea mai veche de pe StackOverflow Ce înseamnă kill -0 $pid într-un script shell? precum și Ce face kill 0 de fapt?. –  > Por Adam Katz.
3 răspunsuri
slm

Acesta este un pic mai greu de ghicit, dar dacă vă uitați în următoarele 2 pagini de man veți vedea următoarele note:

kill(1)

$ man 1 kill
...
If sig is 0, then no signal is sent, but error checking is still performed.
...

kill(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.
...

Deci, semnalul 0 nu va trimite de fapt, de fapt, nimic la PID-ul procesului tău, dar va verifica dacă ai permisiuni pentru a face acest lucru.

Unde ar putea fi util acest lucru?

Un loc evident ar fi dacă ați încerca să determinați dacă aveți permisiuni pentru a trimite semnale unui proces în curs de execuție prin intermediul kill. Ați putea verifica înainte de a trimite semnalul real kill pe care îl doriți, prin includerea unei verificări pentru a vă asigura că kill -0 <PID> a fost mai întâi permisă.

Exemplu

Să presupunem că un proces a fost rulat de root după cum urmează:

$ sudo sleep 2500 &
[1] 15693

Acum, într-o altă fereastră, dacă executăm această comandă, putem confirma că acel PID rulează.

$ pgrep sleep
15693

Acum să încercăm această comandă pentru a vedea dacă avem acces la trimiterea de semnale PID-ului respectiv prin intermediul kill.

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

Deci, funcționează, dar la ieșire se scurge un mesaj de la kill care ne arată că nu avem permisiuni. Nu e mare lucru, pur și simplu prindeți STDERR și trimiteți-l la /dev/null.

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

Exemplu complet

Astfel, am putea face ceva de genul următor, 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

Acum, atunci când rulez cele de mai sus ca utilizator non-root:

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

$ echo $?
1

Cu toate acestea, atunci când este rulat ca root:

$ sudo ~/killer.bash 

$ echo $?
0

$ pgrep sleep
$

Comentarii

  • Aș mai adăuga că acest lucru ar putea fi folosit pentru scripturi multi-proces pentru a vedea dacă un proces este încă în viață. –  > Por prateek61.
  • @slm frumos găsit. Folosind această logică chiar acum într-un script pe care îl scriu, mulțumesc. –  > Por 111—.
  • Prateek61 are dreptate. Nu puteți utiliza pgrep, , ps parsing sau test -e /proc/$PID în scrips portabile, dar kill -0 funcționează peste tot. Dacă vi se dă un PID care poate fi vechi – de exemplu, un /var/run intrare – acesta este modul portabil de a verifica dacă procesul este încă în viață. –  > Por Warren Young.
  • Pe lângă faptul că vă spune dacă PID-ul este în viață, vă spune, de asemenea, dacă încă mai rulează un proces din UID-ul dumneavoastră, deoarece nu aveți permisiunea de a trimite semnale către alte UID-uri (cu excepția cazului în care sunteți root). Astfel, este mai puțin probabil să apară rezultate fals pozitive din cauza reutilizării PID-ului. –  > Por Barmar.
  • Un eșec kill -0 $(pgrep sleep) poate să nu însemne neapărat că ești slab, , va returna fals dacă nu există nici un sleep comandă care rulează, sau dacă sunt mai multe și există una pe care nu o poți ucide, sau dacă unul dintre cei care dorm moare între comenzile pgrep și kill care sunt rulate. –  > Por Stéphane Chazelas.
Gilles ‘SO- nu mai fi rău’

kill -0 (sau varianta sa POSIX mai portabilă kill -s 0) trece prin mișcarea de a trimite un semnal, dar nu trimite de fapt unul. Este o caracteristică a API C de bazăcomanda shell o expune într-un mod simplu.

kill -s 0 -- "$pid" Astfel, testează dacă există un proces în desfășurare cu PID-ul dat (sau PGID dacă $pid este negativ) și dacă procesul curent ar avea permisiunea de a o trimite (oricare dintre procesele din grupul de procese, în cazul unui rezultat negativ). $pid) un semnal. Este în principal o modalitate de a testa dacă un proces (sau un grup de procese) este în viață.

Rețineți că, chiar dacă există un proces în curs de execuție cu PID-ul și permisiunile așteptate, acesta nu este neapărat procesul pe care îl așteptați. Este posibil ca procesul la care vă așteptați să fi murit mai devreme, iar PID-ul său să fi fost reutilizat pentru un proces care nu are legătură cu acesta. Modul corect de monitorizare a proceselor este să lăsați părintele acestora să facă acest lucru – PID-ul unui proces nu este reutilizat până când părintele său nu confirmă moartea acestuia (de aceea zombi există), astfel încât părintele unui proces își poate identifica în mod fiabil copiii prin PID-ul lor.

maxschlepzig

kill -0 $pid vă spune dacă un proces cu $pid există.

În fragmentul

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

blocul ... do something ... este executat dacă există un proces cu PID-ul stocat în /path/to/file.pid și – cu excepția cazului în care fragmentul se execută ca root – dacă PID-ul se execută sub același utilizator.

Standardul POSIX specifică rolul blocului 0 semnalului:

Dacă sig este 0 (semnal nul), se efectuează verificarea erorilor, dar nu se trimite niciun semnal. Semnalul null poate fi utilizat pentru a verifica validitatea pid.

(kill(3p), , POSIX.1-2008 – formulare similară în POSIX.1-2001)

Rețineți că POSIX specifică atât kill -0 și kill -s 0 stilurile de linie de comandă (kill(1p)).

Spre deosebire de interfața kill syscall, interfața kill nu poate fi utilizată pentru a verifica în mod fiabil existența unor PID-uri deținute de alți utilizatori (ca un utilizator normal), de ex:

$ 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

Atunci când se apelează comanda kill syscall se pot distinge în mod fiabil aceste cazuri prin consultarea fișierului errno (a se vedea, de exemplu, un exemplu Python).