Alternatif setara Kinder / lembut / subtler untuk killall (mis. “Endall”)?

17

Bagaimana cara mengakhiri semua proses dengan nama yang sama dengan cara yang lebih lembut daripada killalltidak? Saya tidak ingin mengganggu prosesnya, tetapi biarkan waktu untuk berhenti dengan benar.


Lihat juga:

Bagaimana cara saya membunuh proses di Ubuntu?

Di monitor Sistem, apa perbedaan antara Kill Process dan End Process?

Mengapa killall (kadang-kadang?) Perlu diterapkan dua kali?

tl; dr

gila tentang natty
sumber
1
Dan pertanyaan Anda?
Pilot6
@ Pilot6 diucapkan ulang: apa alternatif yang "lebih lunak" untuk killall?
gila tentang rapi
1
Apa itu "lebih lembut"?
Pilot6
@ Pilot6 "lebih lembut" dalam arti System End's "End" vs "Kill"
gila tentang natty

Jawaban:

43

1. `killall` sudah bagus (SIGTERM)

killallsecara default mengirim SIGTERM. Ini sudah merupakan pendekatan yang bagus yang membuat aplikasi memiliki kesempatan untuk membersihkan diri mereka sendiri. "Sudah mati, sekarang!" Pendekatannya adalah mengirim SIGKILLsinyal, yang mengharuskan Anda menentukannya sebagai opsi killall. Dari Perpustakaan GNU C: Sinyal Pengakhiran :

Makro: int SIGTERM

[...] Ini adalah cara normal untuk dengan sopan meminta sebuah program untuk berakhir.


2. "Proses akhir" Monitor Sistem sama bagusnya (SIGTERM, juga)

Anda menautkan ke pertanyaan tentang Monitor Sistem GNOME. Itu memang digunakan SIGTERMuntuk tindakan "Proses akhir" juga (dan saya sadar saya menentang jawaban untuk pertanyaan itu). Anda dapat menemukannya di kode sumber untuk memverifikasi diri sendiri:

data / menus.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>

15 di sini adalah nomor sinyal. Sinyal 15 adalah SIGTERM. Dan System Monitor telah digunakan dengan SIGTERMbaik sebelum pertanyaan lain diajukan dan dijawab.


Tambahan teknis (sebagai tanggapan terhadap komentar)

Melihat melalui representasi Github git blame, berikut adalah perubahan yang telah dilakukan terhadap bagaimana sinyal-sinyal tersebut dijabarkan dalam kode sumber dari GNOME System Monitor:

383007f2 24 Jul 2013 Diganti kode duplikat untuk mengirim sinyal dengan parameter
GAction 0e766b2d 18 Jul 2013 Menu popup proses port ke GAction
97674c79 3 Okt 2012 Singkirkan struktur
ProcData 38c5296c 3 Jul 2011 Buat lekukan seragam di seluruh file sumber.

Tak satu pun dari ini berubah dari SIGQUITmenjadi SIGTERM, dan yang terakhir adalah dari sebelum pertanyaan terkait diajukan.

hvd
sumber
7
+1 untuk merujuk pada kode sumber! (+2 untuk bertentangan dengan "kebijaksanaan konvensional", seolah-olah;)
gila tentang natty
Nah, sebelum menyatakan bahwa Anda bertentangan dengan jawabannya: apakah Anda memeriksa bahwa semua versi menggunakan kode sumber 15? Itu mungkin telah diubah di beberapa titik sehingga jawaban yang lama bisa 100% benar sehubungan dengan versi yang lama.
Bakuriu
1
@ Bakuriu saya menentang jawaban itu, tetapi poin yang adil, saya akan mencoba untuk mengingat untuk memeriksa bahwa lain kali saya bisa.
hvd
@ Bakuriu di pohon sumber git, git grep 'SIGQUIT'tidak mengungkapkan apa pun. Tidak ada yang terkait dengan sinyal yang ditemukan untuk git grep '>3<'keduanya. Saya menyimpulkan bahwa gnome-system-monitor kemungkinan besar tidak pernah digunakan SIGQUIT.
Ruslan
@Ruslan git grephanya mencari pohon saat ini, bukan seluruh riwayat. Saya menggunakan git blame(sebenarnya setara dengan Github) untuk menggali sedikit lebih dalam, tapi tetap tidak ada.
hvd
5

Jawaban oleh @hvd pada dasarnya benar. Untuk mendukung hal itu lebih jauh lagi, initproses akan mengirim SIGTERMke proses saat Anda mematikan komputer Anda, kemudian setelah penundaan akan mengirim SIGKILLjika mereka belum keluar. Proses tidak dapat menangani / mengabaikan SIGKILL.

Untuk memberikan sedikit lebih detail, jawaban sebenarnya adalah bahwa Anda tidak memiliki cara untuk mengetahui dengan pasti bahwa program menanganinya. SIGTERMadalah sinyal yang paling umum digunakan untuk sopan meminta suatu program untuk berhenti, tetapi semua penanganan sinyal tergantung pada program melakukan sesuatu dengan sinyal.

Dengan kata lain, berdasarkan jawaban yang lain, jika Anda memiliki program yang ditulis oleh @ Jo atau oleh @AlexGreg maka mereka mungkin akan menangani SIGQUITtetapi mungkin tidak SIGTERM, dan karenanya mengirim SIGTERMakan menjadi kurang "lunak" daripada SIGQUIT.

Saya telah menulis beberapa kode sehingga Anda dapat bermain-main dengannya sendiri. Simpan di bawah ini sebagai signal-test.c, lalu kompilasi dengan

gcc -o signal-test signal-test.c

Anda kemudian dapat menjalankannya ./signal-test, dan melihat apa yang terjadi ketika Anda mengirim sinyal yang berbeda dengannya 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;
}

Seperti berdiri, kode menangani SIGTERM dan SIGQUIT dengan anggun. Anda dapat mencoba mengomentari garis signal(SIG...(menggunakan a //di awal baris) untuk menghapus penangan sinyal, kemudian jalankan dan mengirim sinyal lagi. Anda harus dapat melihat output yang berbeda ini:

$ ./signal-test
Terminated

$ ./signal-test
Quit (core dumped)

$ ./signal-test
flag is 15

$ ./signal-test
flag is 3

tergantung pada apakah Anda menangani sinyal atau tidak.

Anda juga dapat mencoba mengabaikan sinyal:

signal(SIGTERM, SIG_IGN);

Jika Anda melakukannya maka pengiriman SIGTERMtidak akan melakukan apa pun, Anda harus menggunakannya SIGKILLuntuk mengakhiri proses.

Lebih detail di man 7 signal. Perhatikan bahwa menggunakan signal()cara ini dianggap non-portabel - jauh lebih mudah daripada alternatifnya!

Satu catatan kaki kecil lainnya - tentang Solaris killallmencoba untuk membunuh semua proses. Mereka semua. Jika Anda menjalankannya sebagai root maka Anda mungkin akan terkejut :)

Roger Light
sumber
1
Ini adalah salah satu alasan saya lebih suka pkill. Alasan lainnya adalah pasangan itu berpasangan pgrep, yang membuatnya lebih mudah untuk memeriksa dengan tepat proses apa yang akan dimatikan, dan yang mana yang memiliki semantik pencocokan yang lebih baik daripada ps | grep.
Random832
1

"Akhiri semua" adalah killall -s SIGQUIT [process name]. Jika Anda menginginkan solusi yang bagus, tentukan alias endall='killall -s SIGQUIT'.

Jos
sumber
13
SIGQUITseperti membuat proses abort(3): itu membuang inti dan kemudian membunuh proses. Ini sama sekali tidak lebih baik / lebih lembut / ramah daripada SIGTERMyang default untuk killall.
Ruslan
3
Untuk proses yang menangani sinyal, SIGQUIT(atau bahkan lebih baik, SIGINT) mungkin diperlakukan lebih 'lembut' daripada SIGTERM, tetapi ini tergantung pada aplikasi. Tidak tertangani, salah satu dari mereka menyebabkan penghentian segera.
R .. GitHub BERHENTI MEMBANTU ICE
1
Ini adalah ide bagus, jika Anda suka membersihkan file inti di seluruh disk Anda.
Nate Eldredge
2
@Qix: Satu hal yang bervariasi per sinyal adalah apakah itu membuat file inti atau tidak pada tindakan default (ketika tidak ditangani oleh aplikasi). Mungkin lebih baik menggunakan sinyal yang tidak menghasilkan file inti.
R .. GitHub BERHENTI MEMBANTU ICE
1
Perlu dicatat bahwa ubuntu menetapkan batas ukuran file inti menjadi 0 secara default, jadi SIGQUIT tidak akan benar-benar menghasilkan file inti (jika tidak ditangani) kecuali jika Anda memodifikasi batasnya.
Roger Light