Kinder / gentler / Subler thay thế tương đương với killall (vd: end endallall)?


17

Làm cách nào để kết thúc tất cả các quy trình có cùng tên theo cách nhẹ nhàng hơn killall? Tôi không muốn làm gián đoạn các quá trình, nhưng hãy để chúng có thời gian để thoát ra.


Xem thêm:

Làm cách nào để diệt các tiến trình trong Ubuntu?

Trong màn hình hệ thống, sự khác biệt giữa Kill Process và End Process là gì?

Tại sao killall (đôi khi?) Cần phải được áp dụng hai lần?

tl; dr


1
Và câu hỏi của bạn là?
Pilot6

@ Pilot6 tái diễn: một sự thay thế "nhẹ nhàng" hơn cho killall là gì?
nutty về natty

1
"Mềm hơn" là gì?
Pilot6

Câu trả lời:


43

1. `killall` đã tốt rồi (SIGTERM)

killalltheo mặc định gửi SIGTERM. Đây đã là cách tiếp cận tốt đẹp để các ứng dụng có cơ hội tự dọn dẹp. "Đi chết đi, ngay bây giờ!" Cách tiếp cận là gửi SIGKILLtín hiệu, yêu cầu chỉ định đó là một tùy chọn killall. Từ Thư viện GNU C: Tín hiệu chấm dứt :

Macro: int SIGTERM

[...] Đó là cách thông thường để lịch sự yêu cầu một chương trình chấm dứt.


2. "Quá trình kết thúc" của System Monitor cũng đẹp không kém (SIGTERM)

Bạn liên kết đến một câu hỏi về Giám sát hệ thống Gnome. Điều đó cũng được sử dụng SIGTERMcho hành động "Kết thúc quá trình" của nó (và tôi nhận ra mình đang mâu thuẫn với câu trả lời cho câu hỏi đó). Bạn có thể tìm thấy nó trong mã nguồn để tự xác minh:

dữ liệu / menu.ui :

<item>
  <attribute name="label" translatable="yes">_End</attribute>
  <attribute name="action">win.send-signal-end</attribute>
  <attribute name="accel">&lt;Primary&gt;e</attribute>
  <attribute name="target" type="i">15</attribute>
</item>

Số 15 ở đây là số tín hiệu. Tín hiệu 15 là SIGTERM. Và System Monitor đã sử dụng SIGTERMtốt trước khi câu hỏi khác được hỏi và trả lời.


Phụ lục kỹ thuật (phản hồi bình luận)

Nhìn qua đại diện Github của git blame, đây là những thay đổi đã được thực hiện đối với cách các tín hiệu được đánh vần trong mã nguồn của Trình giám sát hệ thống Gnome:

383007f2 24 tháng 7 năm 2013 Đã thay thế mã trùng lặp để gửi tín hiệu với các tham số
GAction 0e766b2d 18 tháng 7 năm 2013 Menu bật lên quy trình cổng vào GAction
97674c79 3 tháng 10 năm 2012 Loại bỏ cấu trúc
ProcData 38c5296c 3 tháng 7 năm 2011 Tạo đồng phục thụt vào các tệp nguồn.

Không ai trong số này thay đổi từ SIGQUITthành SIGTERM, và câu hỏi cuối cùng là từ trước khi câu hỏi được liên kết được hỏi.


7
+1 để tham khảo mã nguồn! (+2 vì mâu thuẫn với "sự khôn ngoan thông thường", như đã từng;)
hấp dẫn về sự tự nhiên vào

Chà, trước khi nói rằng bạn đang mâu thuẫn với câu trả lời: bạn đã kiểm tra xem tất cả các phiên bản của mã nguồn có sử dụng 15không? Nó có thể đã được thay đổi tại một số điểm vì vậy câu trả lời cũ có thể đúng 100% đối với phiên bản cũ.
Bakuriu

1
@Bakuriu Tôi có mâu thuẫn với câu trả lời dù bằng cách nào, nhưng điểm công bằng, tôi sẽ cố gắng nhớ để kiểm tra xem lần sau tôi có thể.
hvd

@Bakuriu trong cây git nguồn, git grep 'SIGQUIT'không tiết lộ bất cứ điều gì. Không có gì liên quan đến tín hiệu được tìm thấy cho git grep '>3<'một trong hai. Tôi kết luận rằng rất có thể gnome-system-Monitor chưa bao giờ sử dụng SIGQUIT.
Ruslan

@Ruslan git grepchỉ tìm kiếm cây hiện tại, không phải toàn bộ lịch sử. Tôi đã sử dụng git blame(thực tế là tương đương Github) để đào sâu hơn một chút, nhưng vẫn không có gì.
hvd

5

Câu trả lời của @hvd về cơ bản là chính xác. Để sao lưu nhiều hơn nữa, inittrước tiên quy trình sẽ gửi SIGTERMđến các quy trình khi bạn tắt máy tính, sau đó sẽ trì hoãn SIGKILLnếu chúng chưa thoát. Các quy trình không thể xử lý / bỏ qua SIGKILL.

Để cung cấp thêm một chút chi tiết, câu trả lời thực sự là bạn không có cách nào để biết chắc chắn rằng chương trình xử lý nó. SIGTERMlà tín hiệu thông thường nhất được sử dụng để yêu cầu chương trình thoát một cách lịch sự, nhưng tất cả việc xử lý tín hiệu phụ thuộc vào chương trình thực hiện điều gì đó với tín hiệu.

Nói cách khác, dựa trên các câu trả lời khác, nếu bạn có chương trình được viết bởi @Jos hoặc @AlexGreg thì có lẽ họ sẽ xử lý SIGQUITnhưng có thể không SIGTERM, và do đó việc gửi SIGTERMsẽ ít "mềm" hơn SIGQUIT.

Tôi đã viết một số mã để bạn có thể tự chơi xung quanh nó. Lưu dưới đây signal-test.c, sau đó biên dịch với

gcc -o signal-test signal-test.c

Sau đó, bạn có thể chạy nó ./signal-testvà xem điều gì sẽ xảy ra khi bạn gửi các tín hiệu khác nhau killall -s <signal>.

#include <stdio.h>
#include <signal.h>
#include <unistd.h>

int flag = 0;

void handle_signal(int s)
{
    flag = s;
}

int main(int argc, char *argv[])
{
    signal(SIGTERM, handle_signal);
    signal(SIGQUIT, handle_signal);

    while(flag == 0){
        sleep(1);
    }
    printf("flag is %d\n", flag);
    return flag;
}

Khi nó đứng, mã xử lý cả SIGTERM và SIGQUIT một cách duyên dáng. Bạn có thể thử nhận xét các dòng signal(SIG...(sử dụng a //ở đầu dòng) để loại bỏ trình xử lý tín hiệu, sau đó chạy và gửi lại các tín hiệu. Bạn sẽ có thể thấy các đầu ra khác nhau:

$ ./signal-test
Terminated

$ ./signal-test
Quit (core dumped)

$ ./signal-test
flag is 15

$ ./signal-test
flag is 3

tùy thuộc vào việc bạn xử lý các tín hiệu hay không.

Bạn cũng có thể thử bỏ qua các tín hiệu:

signal(SIGTERM, SIG_IGN);

Nếu bạn làm điều đó thì việc gửi SIGTERMsẽ không làm gì cả, bạn sẽ phải sử dụng SIGKILLđể kết thúc quá trình.

Thêm chi tiết trong man 7 signal. Lưu ý rằng sử dụng signal()theo cách này được coi là không di động - mặc dù vậy nó dễ dàng hơn nhiều so với giải pháp thay thế!

Một chú thích nhỏ khác - về Solaris killallcố gắng giết tất cả các quy trình. Tất cả bọn họ. Nếu bạn chạy nó với quyền root thì bạn có thể ngạc nhiên :)


1
Đây là một trong những lý do tôi thích pkill. Lý do khác là nó kết hợp với nó pgrep, giúp dễ dàng kiểm tra chính xác quá trình nào sẽ bị giết và bản thân nó có ngữ nghĩa phù hợp hơn so với ps | grep.
Random832

1

"Kết thúc tất cả" sẽ là killall -s SIGQUIT [process name]. Nếu bạn muốn một giải pháp ưa thích, xác định alias endall='killall -s SIGQUIT'.


13
SIGQUITgiống như làm cho quá trình abort(3): nó bỏ lõi và sau đó giết chết quá trình. Điều này là không có cách nào đẹp hơn / nhẹ nhàng hơn / tử tế hơn SIGTERMlà mặc định cho killall.
Ruslan

3
Đối với một quy trình xử lý tín hiệu, SIGQUIT(hoặc thậm chí tốt hơn SIGINT) , có thể được xử lý 'nhẹ nhàng' hơn SIGTERM, nhưng điều này tùy thuộc vào ứng dụng. Chưa được xử lý, bất kỳ trong số họ gây ra chấm dứt ngay lập tức.
R ..

1
Đây là một ý tưởng tuyệt vời, nếu bạn thích dọn dẹp các tệp lõi trên đĩa của mình.
Nate Eldredge

2
@Qix: Một điều thay đổi theo tín hiệu là liệu nó có tạo tệp lõi hay không trên hành động mặc định (khi không được ứng dụng xử lý). Có lẽ nên sử dụng các tín hiệu không tạo các tệp cốt lõi.
R ..

1
Điều đáng chú ý là ubfox đặt giới hạn kích thước tệp lõi thành 0 theo mặc định, vì vậy SIGQUIT sẽ không thực sự tạo ra một tệp lõi (nếu không được xử lý) trừ khi bạn sửa đổi giới hạn.
Roger Light
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.