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ì?
kill -0 $pid
trong một kịch bản shell làm gì? cũng như giết 0 thực sự làm gì? .
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ì?
kill -0 $pid
trong một kịch bản shell làm gì? cũng như giết 0 thực sự làm gì? .
Câu trả lời:
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.
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 kill
tí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.
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ừ kill
lệ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ì 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
$
pgrep
, ps
phân tích cú pháp hoặc test -e /proc/$PID
trong các tập lệnh di động, nhưng kill -0
hoạ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/run
mục - đây là cách di động để kiểm tra xem quy trình có còn tồn tại không.
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ó sleep
lệ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.
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ản mà lệ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.
Nó kill -0 $pid
cho bạn biết nếu một quá trình với $pid
tồ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 0
tí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 -0
và kill -s 0
kiểu dòng lệnh (kill (1p)).
Ngược lại với giao diện kill syscall, kill
lệ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 errno
giá trị (ví dụ: Ví dụ Python ).
trap
lệ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ì?