it-swarm-vi.com

Điều gì xảy ra nếu 'kill -9' không hoạt động?

Tôi có một quá trình tôi không thể giết bằng kill -9 <pid>. Vấn đề trong trường hợp như vậy là gì, đặc biệt khi tôi là chủ sở hữu của quá trình đó. Tôi nghĩ không có gì có thể trốn tránh tùy chọn kill.

491
tshepang

kill -9 ( SIGKILL ) luôn hoạt động, miễn là bạn có quyền giết quá trình. Về cơ bản, quá trình phải được bắt đầu bởi bạn và không được setuid hoặc setgid, hoặc bạn phải root. Có một ngoại lệ: ngay cả root cũng không thể gửi tín hiệu gây tử vong cho PID 1 (quá trình init).

Tuy nhiên kill -9 không được bảo đảm để làm việc ngay lập tức. Tất cả các tín hiệu, bao gồm SIGKILL, được phân phối không đồng bộ: hạt nhân có thể mất thời gian để phân phối chúng. Thông thường, việc cung cấp tín hiệu mất tối đa vài micro giây, chỉ cần thời gian để mục tiêu có được một lát cắt thời gian. Tuy nhiên, nếu mục tiêu có chặn tín hiệ , tín hiệu sẽ được xếp hàng cho đến khi mục tiêu bỏ chặn nó.

Thông thường, các quy trình không thể chặn SIGKILL. Nhưng mã kernel có thể và các tiến trình thực thi mã kernel khi chúng gọi gọi hệ thống . Mã hạt nhân chặn tất cả các tín hiệu khi làm gián đoạn cuộc gọi hệ thống sẽ dẫn đến cấu trúc dữ liệu được hình thành xấu ở đâu đó trong kernel hoặc nói chung là trong một số bất biến kernel bị vi phạm. Vì vậy, nếu (do lỗi hoặc xác định sai) một khối cuộc gọi hệ thống vô thời hạn, thực sự có thể không có cách nào để giết quá trình. (Nhưng quá trình will bị giết nếu nó hoàn thành lệnh gọi hệ thống.)

Một quá trình bị chặn trong một cuộc gọi hệ thống là trong giấc ngủ không bị gián đoạn . Lệnh ps hoặc top sẽ (trên hầu hết các đơn vị) hiển thị nó ở trạng thái D (ban đầu là cho ( d isk, tôi nghĩ vậy).

Một trường hợp cổ điển của giấc ngủ dài không thể gián đoạn là các quá trình truy cập các tệp qua NFS khi máy chủ không phản hồi; triển khai hiện đại có xu hướng không áp đặt giấc ngủ không bị gián đoạn (ví dụ: trong Linux, tùy chọn gắn kết intr cho phép tín hiệu làm gián đoạn truy cập tệp NFS).

Đôi khi bạn có thể thấy các mục được đánh dấu Z (hoặc H trong Linux, tôi không biết phân biệt là gì) trong đầu ra ps hoặc top. Đây là những quy trình không phải là quy trình, chúng là các quy trình zombie, không gì khác hơn là một mục trong bảng quy trình, được giữ xung quanh để quy trình cha mẹ có thể được thông báo về cái chết của con của nó. Chúng sẽ biến mất khi tiến trình cha mẹ chú ý (hoặc chết).

577

Đôi khi quá trình tồn tại và không thể bị giết do:

  • là thây ma I E. quá trình mà cha mẹ đã không đọc trạng thái thoát. Quá trình này không tiêu thụ bất kỳ tài nguyên nào ngoại trừ mục nhập PID. Trong top nó được báo hiệu Z
  • giấc ngủ không bị gián đoạn. Điều đó không nên xảy ra nhưng với sự kết hợp của mã hạt nhân lỗi và/hoặc phần cứng lỗi đôi khi nó xảy ra. Phương pháp duy nhất là khởi động lại hoặc chờ đợi. Trong top nó được báo hiệu bởi D.
101
Maciej Piechotka

Có vẻ như bạn có thể có quá trình zombie . Điều này là vô hại: tài nguyên duy nhất mà quá trình zombie tiêu thụ là một mục trong bảng quy trình. Nó sẽ biến mất khi quá trình cha mẹ chết hoặc phản ứng với cái chết của con nó.

Bạn có thể xem liệu quy trình có phải là zombie hay không bằng cách sử dụng top hoặc lệnh sau:

ps aux | awk '$8=="Z" {print $2}'
32
Josh

Kiểm tra của bạn /var/log/kern.log/var/log/dmesg (hoặc tương đương) cho bất kỳ manh mối nào. Theo kinh nghiệm của tôi, điều này chỉ xảy ra với tôi khi kết nối mạng của NFS bị treo đột ngột hoặc trình điều khiển thiết bị bị hỏng. Tôi có thể xảy ra nếu một ổ cứng bị hỏng.

Bạn có thể sử dụng lsof để xem tập tin thiết bị nào mà quá trình đã mở.

26
LawrenceC

Nếu @ Maciej 's và @ Gilles câu trả lời của bạn không giải quyết được vấn đề của bạn và bạn không nhận ra quy trình (và hỏi nó là gì với bản phân phối của bạn 't bật lên câu trả lời). Kiểm tra Rootkit và bất kỳ dấu hiệu nào khác mà bạn đã sở hữu . Một rootkit không chỉ có khả năng ngăn bạn giết quá trình. Trong thực tế, nhiều người có khả năng ngăn bạn nhìn thấy chúng. Nhưng nếu họ quên sửa đổi 1 chương trình nhỏ, họ có thể bị phát hiện (ví dụ: họ đã sửa đổi top, nhưng không phải htop). Nhiều khả năng đây không phải là trường hợp nhưng an toàn tốt hơn là xin lỗi.

17
xenoterracide

Kill thực sự có nghĩa là gửi tín hiệu. có nhiều tín hiệu bạn có thể gửi. giết -9 là một tín hiệu đặc biệt.

Khi gửi tín hiệu ứng dụng xử lý nó. nếu không phải là hạt nhân đối phó với nó. để bạn có thể bẫy tín hiệu trong ứng dụng của bạn.

Nhưng tôi đã nói kill -9 thật đặc biệt. Điều đặc biệt là ứng dụng không nhận được nó. nó đi thẳng vào kernel mà sau đó thực sự giết chết ứng dụng ở cơ hội đầu tiên có thể. nói cách khác giết chết nó

kill -15 gửi SIGTERM tín hiệu là viết tắt của TÍN HIỆU TÍN HIỆU nói cách khác nói cho ứng dụng thoát. Đây là cách thân thiện để nói với một ứng dụng đã đến lúc tắt máy. nhưng nếu ứng dụng không phản hồi kill -9 sẽ giết nó.

nếu kill -9 không hoạt động thì có lẽ điều đó có nghĩa là kernel của bạn đã hết. khởi động lại theo thứ tự. Tôi không thể nhớ điều đó đã từng xảy ra.

11
DeveloperChris

Đầu tiên, hãy kiểm tra xem đó có phải là quá trình Zombie không (rất có thể):

ps -Al

Bạn sẽ thấy một cái gì đó như:

0 Z  1000 24589     1  0  80   0 -     0 exit   ?        00:00:00 soffice.bin <defunct>

(Lưu ý "Z" bên trái)

Nếu cột thứ 5 không phải là 1, thì có nghĩa là nó có quá trình cha. Thử giết id tiến trình cha mẹ đó.

Nếu PPID của nó = 1, ĐỪNG GIẾT NÓ !!, hãy nghĩ những thiết bị hoặc quy trình nào khác có thể liên quan đến nó.

Ví dụ: nếu bạn đang sử dụng thiết bị được gắn hoặc samba, hãy thử ngắt kết nối thiết bị. Điều đó có thể giải phóng quá trình Zombie.

GHI CHÚ : Nếu ps -Al (hoặc top) hiển thị "D" thay vì "Z", nó có thể liên quan đến mount từ xa (như NFS). Theo kinh nghiệm của tôi, khởi động lại là cách duy nhất để đi đến đó, nhưng bạn có thể kiểm tra các câu trả lời khác bao gồm trường hợp đó chi tiết hơn.

11
lepe

Quá trình init miễn dịch với SIGKILL.

Điều này cũng đúng với các luồng nhân, tức là "các quy trình" với PPID bằng 0.

10
jlliagre

Như những người khác đã đề cập, một quá trình trong giấc ngủ không bị gián đoạn có thể bị giết ngay lập tức (hoặc, trong một số trường hợp, tất cả). Đáng lưu ý rằng một trạng thái quy trình khác, TASK_KILLABLE, đã được thêm vào để giải quyết vấn đề này trong một số trường hợp nhất định, đặc biệt là trường hợp phổ biến trong đó quy trình đang chờ trên NFS. Xem http://lwn.net/Articles/288056/

Thật không may, tôi không tin rằng nó được sử dụng ở bất cứ đâu trong kernel trừ NFS.

10
user36054

Làm một kịch bản nhỏ giúp tôi rất nhiều hãy xem!

Bạn có thể sử dụng nó để giết bất kỳ tiến trình nào có tên đã cho trong đường dẫn của nó (chú ý đến điều này !!) Hoặc bạn có thể giết bất kỳ quy trình nào của người dùng đã cho bằng cách sử dụng tham số "-u username".

#!/bin/bash

if [ "$1" == "-u" ] ; then\n
        PID=`grep "$2" /etc/passwd | cut -d ":" -f3`
        processes=`ps aux | grep "$PID" | egrep -v "PID|ps \-au|killbyname|grep" | awk '{ print $2}'`
        echo "############# Killing all processes of user: $2 ############################"
else
        echo "############# Killing processes by name: $1 ############################"
        processes=`ps aux | grep "$1" | egrep -v "killbyname|grep" | awk '{ print $2}' `
fi


for process in $processes ; do
        # "command" stores the entire commandline of the process that will be killed
        #it may be useful to show it but in some cases it is counter-productive
        #command=`ps aux | grep $process | egrep -v "grep" | awk '{ print $2 }'`
        echo "Killing process: $process"
        echo ""
        kill -9 $process
done
6
user36035

Có những trường hợp ngay cả khi bạn gửi kill -9 đến một tiến trình, pid đó sẽ dừng lại, nhưng quá trình sẽ tự động khởi động lại (ví dụ, nếu bạn thử nó với gnome-panel, nó sẽ khởi động lại): đó có thể là trường hợp ở đây không?

5
dag729

từ ở đây ban đầ :

kiểm tra nếu strace cho thấy bất cứ điều gì

strace -p <PID>

hãy thử đính kèm vào quy trình với gdb

gdb <path to binary> <PID>

nếu quá trình đang tương tác với một thiết bị mà bạn có thể ngắt kết nối, hãy tháo mô-đun hạt nhân hoặc ngắt kết nối/rút phích cắm vật lý ... thì hãy thử điều đó.

2
nmz787

Tôi đã có loại vấn đề này. Đây là một chương trình mà tôi đã khởi chạy với strace và bị gián đoạn với Ctrl + C. Nó đã kết thúc ở trạng thái T (truy tìm hoặc dừng). Tôi không biết chính xác nó đã xảy ra như thế nào, nhưng nó không thể bị giết bằng SIGKILL.

Tóm lại, tôi đã giết nó với gdb:

gdb -p <PID>
> kill
Kill the program being debugged? (y or n) y
> quit
1

Dựa trên manh mối từ câu trả lời của gilles, tôi đã có một quy trình được đánh dấu là "Z" ("" trong ps) đang sử dụng tài nguyên hệ thống, nó thậm chí còn có một cổng mở là LISTEN'ing và bạn có thể kết nối với nó. Đây là sau khi thực hiện một kill -9 trên đó. Cha mẹ của nó là "1" (tức là init) vì vậy về mặt lý thuyết nó sẽ biến mất. Nhưng nó không phải, nó đã bám xung quanh, mặc dù không chạy.

Vì vậy, trong trường hợp của tôi, đó là zombie nhưng vẫn tiêu tốn tài nguyên ... FWIW.

Và nó không thể bị giết bởi kill -9.

Và cha mẹ của nó là init nhưng nó không được gặt hái (dọn sạch). I E. init đã có một đứa trẻ zombie.

Và khởi động lại là không cần thiết để khắc phục vấn đề. Mặc dù khởi động lại "sẽ có tác dụng" xung quanh vấn đề/làm cho nó tắt nhanh hơn. Chỉ cần không duyên dáng, mà vẫn có thể.

Và đó là một cổng LISTEN được sở hữu bởi một quá trình zombie (và một vài cổng khác giống như trạng thái CLOSE_WAIT được kết nối localhost với localhost). Và nó thậm chí vẫn chấp nhận kết nối. Ngay cả như một thây ma. Tôi đoán nó đã không được dọn dẹp các cổng nhưng các kết nối đến vẫn được thêm vào hồ sơ tồn đọng của cổng nghe tcp, mặc dù chúng không có cơ hội được chấp nhận.

Hóa ra tôi có một luồng nội bộ trong đó đang thực hiện một "cuộc gọi hệ thống" (trong trường hợp này là ioctl), phải mất vài giờ để quay lại (điều này đã được mong đợi). Rõ ràng hệ thống không thể giết nó "mọi cách" cho đến khi nó trở lại từ đó. Sau một vài giờ, nó đã được dọn sạch và tất cả các ổ cắm đều tự động đóng lại, v.v. như mong đợi. Đó là một thời gian chết mệt mỏi!

Ngoài ra, hãy kiểm tra dmesg để xem có hoảng loạn kernel không (ví dụ: lỗi kernel).

0
rogerdpack