`Kill -0 $ pid` trong tập lệnh shell làm gì?


Câu trả lời:


136

gửi tín hiệu 0đến một PIDchỉ định sẽ kiểm tra xem có bất kỳ quá trình nào được đưa ra PIDđang chạy hay không và bạn có quyền gửi tín hiệu đến nó.

Để biết thêm thông tin, xem các trang 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.
...

7
Vị trí của thông tin này (nếu nó tồn tại) phụ thuộc rất nhiều vào hệ thống. Trên các hệ thống dựa trên Debian gần đây, sử dụng man 2 killthay thế.
Todd A. Jacobs

2
Cả hai man 1 killman 2 killđã có nó trên hệ thống Fedora 20 của tôi. Thật khó để nhận ra, chôn vùi trong cả hai trang người đàn ông đó.
slm

Hoặc dựa vào hướng dẫn sử dụng posix thay thế: If sig is 0 (the null signal), error checking is performed but no signal is actually sent. The null signal can be used to check the validity of pid. pubs.opengroup.org/onlinepub/009695399/fifts/kill.html
Thomas Hughes

2
Tôi cảm thấy như lệnh man 2 killnằm ngoài sửa đổi thứ 1 :)
JBaczuk

126

Đây là một câu hỏi hay vì ...

... có thể khó tìm tài liệu về tín hiệu đặc biệt này. Bất chấp những gì người khác đã nói, đề cập duy nhất về tín hiệu này trong man 1 killcác hệ thống dựa trên Debian là:

Các tín hiệu đặc biệt hữu ích bao gồm HUP, INT, KILL, STOP, CONT và 0.

Không đặc biệt hữu ích, đặc biệt nếu bạn chưa biết tín hiệu này làm gì. Nó cũng không được liệt kê theo đầu ra của kill -l, vì vậy bạn sẽ không biết về nó trừ khi bạn đã biết về nó.

Nơi tìm tài liệu

Trên các hệ thống Debian và Ubuntu, phần đầu ra của phần man 2 killnói:

Nếu sig bằng 0, thì không có tín hiệu nào được gửi, nhưng việc kiểm tra lỗi vẫn được thực hiện; điều này có thể được sử dụng để kiểm tra sự tồn tại của ID tiến trình hoặc ID nhóm quy trình.

Nó tốt cho cái gì

Bạn có thể sử dụng kill -0để kiểm tra xem một tiến trình có đang chạy hay không. Hãy xem xét những ví dụ này.

# Kill the process if it exists and accepts signals from
# the current user.
sleep 60 &
pid=$!
kill -0 $pid && kill $pid

# Check if a PID exists. When missing, this should result
# in output similar to:
#    bash: kill: (6228) - No such process
#    Exit status: 1
kill -0 $pid; echo "Exit status: $?"

Bạn cũng có thể sử dụng kill -0để xác định xem người dùng hiện tại có quyền báo hiệu một quy trình nhất định hay không. Ví dụ:

# See if you have permission to signal the process. If not,
# this should result in output similar to:
#     bash: kill: (15764) - Operation not permitted
#     Exit status: 1
sudo sleep 60 &
kill -0 $!; echo "Exit status: $?"

Trên mac và BSD, nó cũng được ghi lại trong kill(2) Đây là đoạn trích:The kill() function sends the signal specified by sig to pid, a process or a group of processes. Typically, Sig will be one of the signals specified in sigaction(2). A value of 0, however, will cause error checking to be performed (with no signal being sent). This can be used to check the validity of pid.
lukecampbell

8
Đây phải là câu trả lời được chấp nhận. Tốt hơn nhiều so với cái khác. tài liệu về tín hiệu 0 rất khó xác định. Nó bị chôn vùi trong killtrang man: "Nếu sig bằng 0, thì không có tín hiệu nào được gửi, nhưng việc kiểm tra lỗi vẫn được thực hiện."
slm

6

Lệnh này kiểm tra quá trình với PID trong $ pid còn sống.


1
Trang man nói: "Nếu sig bằng 0, thì không có tín hiệu nào được gửi, nhưng việc kiểm tra lỗi vẫn được thực hiện." Chúng tôi đề cập đến những gì kiểm tra lỗi ở đây?
gjain

2
-1, vì một quy trình với PID $pidcó thể đang chạy nhưng bạn không có quyền gửi tín hiệu đến nó.
lùn

2
@dwalter: Nếu bạn không có sự cho phép, bạn sẽ nhận được một EPERM. Nếu nó không tồn tại, bạn sẽ nhận được ESRCH. Các kill(1)sẽ in một lỗi khác nhau cho mỗi người. Vì vậy, bạn có thể biết liệu pid còn sống hay không, bất kể bạn có quyền gửi tín hiệu hay không. Hơn nữa, cách sử dụng điển hình kill -0là để xem pid còn sống hay không, ngay cả khi nó không luôn được sử dụng đúng cách. Tôi muốn nói câu trả lời này là chính xác (ngoài chính tả).
camh

3
@camh: không có giá trị trả về kill -0 $pidsẽ giống nhau trong cả hai trường hợp. Nó sẽ trả về 1để bạn không thể nói mà không phân tích cú pháp về killviệc quá trình có chạy hay không, nếu bạn không có quyền gửi tín hiệu đến nó. EDIT: có Tôi biết rằng nó được sử dụng hầu hết thời gian để kiểm tra xem một quy trình có còn tồn tại không, nhưng điều này là sai trừ khi bạn có thể đảm bảo rằng bạn có quyền gửi tín hiệu (ví dụ: là root)
dwalter

2
@dwalter: Quan điểm của tôi là câu trả lời là đúng. Bạn đã cố gắng trở thành người phạm tội và chỉ ra rằng có một trường hợp lỗi khác, nhưng tôi nói với bạn rằng về mặt kỹ thuật câu trả lời cũng bao gồm trường hợp đó vì killbash tích hợp (câu hỏi được gắn thẻ bash) đưa ra loại lỗi trên stderr và dấu hiệu của một lỗi trong mã trả lại của nó. Đó là, "Lệnh này kiểm tra [liệu] quá trình với PID trong $ pid có còn sống hay không" là hoàn toàn chính xác nếu bạn diễn giải đầu ra chính xác. [Tôi sẽ không bình luận nếu bạn không nói rằng bạn đã trả lời -1 cho câu trả lời. Nhận xét của bạn là hợp lệ].
camh

6

Giết -0 $ pid là để kiểm tra xem quy trình với pid có tồn tại hay không.

Hãy cẩn thận trong khi sử dụng 'kill -0 $ pid' để kiểm tra sự tồn tại của quy trình vì

  1. Một khi quá trình dự định thoát thì pid của nó có thể được phân bổ cho quá trình mới được tạo khác. (Vì vậy, người ta không thể chắc chắn rằng quá trình cụ thể còn sống hay không)

  2. Trong trường hợp quá trình Zombie, đứa trẻ nào đang đợi cha mẹ gọi chờ. Ở đây, nó giữ $ pid và cho kết quả khả quan trong khi quá trình đó không chạy.


1

Giết -0 $ pid được sử dụng để kiểm tra xem một tiến trình đang chạy với $ pid có còn sống hay không. Nhưng điều này có thể khó khăn, vì ID tiến trình có thể được chỉ định lại, sau khi thoát quy trình và quy trình mới chạy. Người ta có thể sử dụng killall -0 để biết về một quy trình cụ thể đang chạy hay không.


0

Gửi EXITtín hiệu, hoặc 0đến một quá trình sẽ:

  1. Kiểm tra sự tồn tại của một quá trình.
  2. Thực hiện kiểm tra lỗi khác nhau trên quy trình (PID, PGID, v.v ...).
  3. Nó sẽ không gửi bất kỳ đầu ra nào stdoutkhi thành công.
  4. Gửi một thông báo lỗi stderrnếu có gì đó không đúng.
  5. Cung cấp cho bạn một dương tính giả nếu quá trình không còn tồn tại (ví dụ Zombie).

Rõ ràng hơn, một chức năng hữu ích cho các tập lệnh shell của bạn sẽ là:

function isProcess ()
{
    kill -s EXIT $1 2> /dev/null
}

Điều này trả về không có văn bản nào stdoutkhi thành công, nhưng thông báo lỗi đến stderrkhi thất bại (nhưng tôi đã chuyển hướng thông báo lỗi đó /dev/null).

Nếu bạn lo ngại về tình trạng quá trình không còn tồn tại / zombie , thì bạn cần sử dụng ps, tốt nhất là với công --no-headerstắc.

#!/bin/ksh

function trim ()
{
    echo -n "$1" | tr -d [:space:]
}

function getProcessStatus ()
{
    trim $(ps -p $1 -o stat --no-headers)
}

function isZombie ()
{
    typeset processStatus=$(getProcessStatus $1)

    [[ "$processStatus" == "Z" ]]
    return $?
}
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.