`Kill -0` làm gì?


61

Gần đây tôi đã bắt gặp điều này trong một kịch bản shell.

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

Không gì kill -0 ...làm gì?


2
Xem ở đây nếu bạn bối rối về sự khác biệt của traplệnh b / w Bash và 0 so với tín hiệu 0 từ kill: Tín hiệu 0 trong lệnh bẫy là gì?
slm

Câu trả lời:


76

Cái này hơi khó để lượm lặt nhưng nếu bạn xem trong 2 trang nam sau đây bạn sẽ thấy các ghi chú sau:

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

Vì vậy, tín hiệu 0 trên thực tế sẽ không gửi bất cứ thứ gì đến bộ xử lý của bạn, nhưng sẽ kiểm tra xem bạn có quyền để làm như vậy không.

Điều này có thể hữu ích ở đâu?

Một nơi rõ ràng sẽ là nếu bạn đang cố xác định xem bạn có quyền gửi tín hiệu đến một quy trình đang chạy hay không kill. Bạn có thể kiểm tra trước khi gửi killtín hiệu thực tế mà bạn muốn, bằng cách gói một kiểm tra để đảm bảo rằng đó kill -0 <PID>là lần đầu tiên được cho phép.

Thí dụ

Nói rằng một quá trình đã được chạy bởi root như sau:

$ sudo sleep 2500 &
[1] 15693

Bây giờ trong một cửa sổ khác nếu chúng ta chạy lệnh này, chúng ta có thể xác nhận rằng PID đang chạy.

$ pgrep sleep
15693

Bây giờ chúng ta hãy thử lệnh này để xem liệu chúng ta có quyền truy cập để gửi tín hiệu PID đó qua không kill.

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

Vì vậy, nó hoạt động, nhưng đầu ra đang rò rỉ một thông báo từ killlệnh mà chúng tôi không có quyền. Không phải là một vấn đề lớn, chỉ cần bắt STDERR và gửi nó đến /dev/null.

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

Ví dụ hoàn chỉnh

Vì vậy, sau đó chúng ta có thể làm một cái gì đó như thế này , 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

Bây giờ khi tôi chạy ở trên với tư cách là người dùng không root:

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

$ echo $?
1

Tuy nhiên, khi nó chạy như root:

$ sudo ~/killer.bash 

$ echo $?
0

$ pgrep sleep
$

9
Tôi cũng sẽ thêm điều này có thể được sử dụng cho các tập lệnh multi-Proc để xem liệu một quy trình có còn tồn tại không.
prateek61

1
@slm đẹp tìm. Sử dụng logic này ngay bây giờ trong một kịch bản tôi đang viết, cảm ơn.
111 ---

12
Prateek61 đã đúng. Bạn không thể sử dụng pgrep, psphân tích cú pháp hoặc test -e /proc/$PIDtrong các tập lệnh di động, nhưng kill -0hoạt động ở mọi nơi. Nếu bạn được cung cấp một PID có thể cũ - ví dụ như một /var/runmục - đây là cách di động để kiểm tra xem quy trình có còn tồn tại không.
Warren Young

1
Ngoài việc cho bạn biết nếu PID còn sống, nó còn cho bạn biết một cách hiệu quả nếu nó vẫn đang chạy một quy trình từ UID của bạn, vì bạn không có quyền gửi tín hiệu đến các UID khác (trừ khi bạn đã root). Điều này làm cho dương tính giả do tái sử dụng PID ít có khả năng.
Barmar

Thất bại kill -0 $(pgrep sleep)có thể không nhất thiết có nghĩa là bạn yếu , nó sẽ trả về sai nếu không có sleeplệnh nào chạy hoặc nếu có nhiều hơn một và bạn không thể giết hoặc nếu một trong những giấc ngủ chết giữa pgrep và kill các lệnh đang được chạy.
Stéphane Chazelas

22

kill -0(hoặc biến thể POSIX di động hơn của nó kill -s 0) trải qua chuyển động gửi tín hiệu, nhưng thực tế không gửi tín hiệu. Đây là một tính năng của API C cơ bảnlệnh shell hiển thị theo cách đơn giản.

kill -s 0 -- "$pid"do đó kiểm tra xem có một quy trình đang chạy với PID đã cho (hoặc PGID nếu $pidâm tính) hay không và liệu quy trình hiện tại có được phép gửi nó không (bất kỳ quy trình nào trong nhóm quy trình trong trường hợp có âm $pid). Đây chủ yếu là một cách để kiểm tra xem một quy trình (hoặc nhóm quy trình) còn sống hay không.

Hãy nhớ rằng ngay cả khi có một quy trình đang chạy với các quyền và quyền dự kiến, thì đây không nhất thiết là quy trình mà bạn mong đợi. Có thể quy trình mà bạn mong đợi đã chết trước đó và PID của nó đã được sử dụng lại cho một quy trình không liên quan. Cách đúng đắn để giám sát các quá trình là bằng cách để cha mẹ chúng làm điều đó - một quy trình không được sử dụng lại cho đến khi cha mẹ của nó thừa nhận cái chết của nó (đó là lý do tại sao zombie tồn tại), vì vậy cha mẹ của một quá trình có thể xác định được con cái của họ một cách đáng tin cậy.


0

kill -0 $pidcho bạn biết nếu một quá trình với $pidtồn tại.

Trong đoạn trích

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

khối ... do something ...được thực thi nếu một quá trình với PID được lưu trữ /path/to/file.pidđang chạy - và - trừ khi đoạn mã chạy dưới quyền root - nếu PID chạy dưới cùng một người dùng.

Tiêu chuẩn POSIX chỉ định vai trò của 0tín hiệu:

Nếu sig bằng 0 (tín hiệu null), kiểm tra lỗi được thực hiện nhưng không có tín hiệu nào thực sự được gửi. Tín hiệu null có thể được sử dụng để kiểm tra tính hợp lệ của pid.

(giết (3p), POSIX.1-2008 - từ ngữ tương tự trong POSIX.1-2001)

Lưu ý rằng POSIX chỉ định cả hai kill -0kill -s 0kiểu dòng lệnh (kill (1p)).

Ngược lại với giao diện kill syscall, killlệnh không thể được sử dụng để kiểm tra một cách đáng tin cậy sự tồn tại của các PID do người dùng khác sở hữu (như một người dùng bình thường), ví dụ:

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

so với

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

Khi gọi lệnh giết tòa nhà, người ta có thể phân biệt các trường hợp này một cách đáng tin cậy thông qua việc xem xét errnogiá trị (ví dụ: Ví dụ Python ).

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.