Apa yang dilakukan `kill -0`?

61

Saya baru-baru menemukan ini dalam skrip shell.

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

Apa yang kill -0 ...harus dilakukan

slm
sumber
2
Lihat di sini jika Anda bingung tentang perbedaan antara trapperintah Bash dan Bash dan 0 vs sinyal 0 dari kill: Apa sinyal 0 dalam perintah perangkap?
slm

Jawaban:

76

Yang ini agak sulit didapat, tetapi jika Anda melihat 2 halaman manual berikut, Anda akan melihat catatan berikut:

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

Jadi sinyal 0 sebenarnya tidak akan mengirim apa pun ke PID proses Anda, tetapi akan memeriksa apakah Anda memiliki izin untuk melakukannya.

Di mana ini bisa berguna?

Satu tempat yang jelas adalah jika Anda mencoba menentukan apakah Anda memiliki izin untuk mengirim sinyal ke proses yang sedang berjalan kill. Anda dapat memeriksa sebelum mengirim killsinyal aktual yang Anda inginkan, dengan membungkus tanda centang untuk memastikan yang kill -0 <PID>pertama diizinkan.

Contoh

Katakanlah suatu proses dijalankan oleh root sebagai berikut:

$ sudo sleep 2500 &
[1] 15693

Sekarang di jendela lain jika kita menjalankan perintah ini, kita dapat mengkonfirmasi bahwa PID sedang berjalan.

$ pgrep sleep
15693

Sekarang mari kita coba perintah ini untuk melihat apakah kita memiliki akses untuk mengirim sinyal PID melalui kill.

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

Jadi itu berfungsi, tetapi hasilnya bocor pesan dari killperintah bahwa kita tidak memiliki izin. Bukan masalah besar, cukup tangkap STDERR dan kirimkan ke /dev/null.

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

Contoh lengkap

Jadi kita bisa melakukan sesuatu seperti ini 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

Sekarang ketika saya menjalankan di atas sebagai pengguna non-root:

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

$ echo $?
1

Namun ketika dijalankan sebagai root:

$ sudo ~/killer.bash 

$ echo $?
0

$ pgrep sleep
$
slm
sumber
9
Saya juga akan menambahkan ini dapat digunakan untuk skrip multi-proc untuk melihat apakah suatu proses masih hidup.
prateek61
1
@slm cari yang bagus. Menggunakan logika ini sekarang dalam skrip yang saya tulis, terima kasih.
111 ---
12
Prateek61 benar. Anda tidak dapat menggunakan pgrep, psmem-parsing atau test -e /proc/$PIDdalam skrip portabel, tetapi kill -0bekerja di mana-mana. Jika Anda diberi PID yang mungkin basi - misalnya /var/runentri - ini adalah cara portabel untuk memeriksa apakah prosesnya masih hidup.
Warren Young
1
Selain memberi tahu Anda jika PID masih hidup, PID itu juga memberi tahu Anda jika masih menjalankan proses dari UID Anda, karena Anda tidak memiliki izin untuk mengirim sinyal ke UID lain (kecuali jika Anda root). Hal ini membuat kesalahan positif karena penggunaan kembali PID menjadi kurang mungkin.
Barmar
Gagal kill -0 $(pgrep sleep)mungkin tidak berarti Anda lemah , itu akan kembali palsu jika tidak ada sleepperintah yang berjalan, atau jika ada lebih dari satu dan ada satu yang tidak dapat Anda bunuh, atau jika salah satu dari tidur mati di antara pgrep dan kill perintah dijalankan.
Stéphane Chazelas
22

kill -0(atau varian POSIX yang lebih portabel kill -s 0) melalui gerakan mengirim sinyal, tetapi sebenarnya tidak mengirimnya. Ini adalah fitur dari API C yang mendasari bahwa perintah shell mengekspos dengan cara yang mudah.

kill -s 0 -- "$pid"dengan demikian menguji apakah ada proses yang berjalan dengan PID yang diberikan (atau PGID jika $pidnegatif), dan apakah proses saat ini akan memiliki izin untuk mengirimkannya (salah satu proses dalam kelompok proses jika ada negatif $pid) sinyal. Sebagian besar cara untuk menguji apakah suatu proses (atau kelompok proses) masih hidup.

Perlu diingat bahwa meskipun ada proses yang berjalan dengan PID dan izin yang diharapkan, ini belum tentu proses yang Anda harapkan. Mungkin saja proses yang Anda harapkan mati sebelumnya dan PID-nya digunakan kembali untuk proses yang tidak terkait. Cara yang tepat untuk memantau proses adalah dengan membiarkan orang tua mereka melakukannya - PID proses tidak digunakan kembali sampai orang tuanya mengakui kematiannya (itulah sebabnya zombie ada), sehingga orang tua proses dapat andal mengidentifikasi anak-anaknya dengan PID mereka.

Gilles 'SANGAT berhenti menjadi jahat'
sumber
0

The kill -0 $pidmemberitahu Anda jika suatu proses dengan $pidada.

Di cuplikan

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

blok ... do something ...dijalankan jika proses dengan PID yang disimpan dalam /path/to/file.pidberjalan - dan - kecuali snippet berjalan sebagai root - jika PID berjalan di bawah pengguna yang sama.

Standar POSIX menentukan peran 0sinyal:

Jika sig adalah 0 (sinyal nol), pengecekan error dilakukan tetapi sebenarnya tidak ada sinyal yang dikirim. Sinyal nol dapat digunakan untuk memeriksa validitas pid.

(kill (3p), POSIX.1-2008 - kata-kata yang mirip di POSIX.1-2001)

Perhatikan bahwa POSIX menentukan keduanya kill -0dan kill -s 0gaya baris perintah (kill (1p)).

Berbeda dengan antarmuka syscall kill, killperintah tidak dapat digunakan untuk memeriksa keberadaan PID yang dimiliki oleh pengguna lain (sebagai pengguna normal) secara andal, misalnya:

$ 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

Saat memanggil kill syscall, seseorang dapat dengan andal membedakan kasus-kasus ini dengan melihat errnonilainya (lih. Mis. Contoh Python ).

maxschlepzig
sumber