Як я закінчую всі процеси з тим самим іменем більш щадним чином, ніж killall
це? Я не хочу переривати процеси, але залишаю їм час для належного виходу.
Дивись також:
У системному моніторі, яка різниця між Kill Process і End Process?
Як я закінчую всі процеси з тим самим іменем більш щадним чином, ніж killall
це? Я не хочу переривати процеси, але залишаю їм час для належного виходу.
Дивись також:
У системному моніторі, яка різниця між Kill Process і End Process?
Відповіді:
killall
за замовчуванням надсилає SIGTERM
. Це вже приємний підхід, який залишає додаткам можливість прибирати після себе. "Помри вже, прямо зараз!" Підхід полягає в тому, щоб надіслати SIGKILL
сигнал, який вимагає вказати це як варіант для killall
. З бібліотеки GNU C: сигнали про припинення :
Макрос: int SIGTERM
[...] Це нормальний спосіб ввічливо попросити програму припинити.
Ви посилаєтесь на питання про монітор системи GNOME. Це також використовує SIGTERM
для своєї дії "Кінцевий процес" (і я розумію, що я суперечу відповіді на це питання). Ви можете знайти його у вихідному коді, щоб підтвердити себе:
<item>
<attribute name="label" translatable="yes">_End</attribute>
<attribute name="action">win.send-signal-end</attribute>
<attribute name="accel"><Primary>e</attribute>
<attribute name="target" type="i">15</attribute>
</item>
15 тут - номер сигналу. Сигнал 15 є SIGTERM
. І System Monitor використовував SIGTERM
задовго до того, як було задано та відповіли на інше питання.
Ознайомившись із представленням Github git blame
, ось такі зміни, які були внесені до того, як сигнали прописані у вихідному коді GNOME System Monitor:
383007f2 24 липня 2013 Замінений дублюючий код для надсилання сигналів з параметрами
GAction 0e766b2d 18 липня 2013 Спливаюче меню порту процесу на GAction
97674c79 3 жовтня 2012 Позбавтеся від структури
ProcData 38c5296c 3 липня 2011 Зробіть відступ рівномірним у вихідних файлах.
Жодне з них не змінилося з SIGQUIT
на SIGTERM
, і останнє було з того, як було задано пов'язане питання.
15
? Він може бути змінений в якийсь момент, щоб стара відповідь могла бути на 100% правильною щодо старої версії.
git grep 'SIGQUIT'
нічого не виявляє. Нічого, пов'язаного із сигналами, не знайдено для git grep '>3<'
жодного. Я роблю висновок, що, швидше за все, gnome-монітор-система ніколи не використовувався SIGQUIT
.
git grep
шукає лише поточне дерево, а не всю історію. Я використовував git blame
(фактично еквівалент Github), щоб копати трохи глибше, але все одно нічого.
Відповідь @hvd в основному правильна. Щоб зробити резервне копіювання ще більше, init
процес спочатку надсилатиметься SIGTERM
до процесів, коли ви вимикаєте комп'ютер, а потім після затримки надсилатиметься, SIGKILL
якщо вони ще не вийшли. Процеси не можуть впоратися / ігноруватиSIGKILL
.
Щоб дати трохи більше деталей, справжня відповідь полягає в тому, що ви не можете точно знати, що програма обробляє це. SIGTERM
це найбільш звичайний сигнал, який використовується для ввічливого прохання програми вийти, але все обробка сигналу залежить від того, яка програма щось робить із сигналом.
По-іншому, виходячи з інших відповідей, якби у вас була програма, написана @Jos або @AlexGreg, вони, ймовірно, будуть обробляти, SIGQUIT
але, можливо, ні SIGTERM
, і, отже, надсилатиSIGTERM
буде менш "м'якою", ніжSIGQUIT
.
Я написав якийсь код, щоб ви могли самі пограти з ним. Збережіть нижче як signal-test.c
, а потім компілюйте з
gcc -o signal-test signal-test.c
Потім ви можете запустити його ./signal-test
і подивитися, що відбувається, коли ви надсилаєте різні сигнали 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;
}
На сьогоднішній день код обробляє SIGTERM і SIGQUIT витончено. Ви можете спробувати коментувати лінії signal(SIG...
(використовуючи a //
на початку рядка), щоб видалити обробник сигналу, після чого запустіть і надішліть сигнали знову. Ви повинні мати можливість бачити ці різні результати:
$ ./signal-test
Terminated
$ ./signal-test
Quit (core dumped)
$ ./signal-test
flag is 15
$ ./signal-test
flag is 3
залежно від того, обробляєте ви сигнали чи ні.
Ви також можете спробувати ігнорувати сигнали:
signal(SIGTERM, SIG_IGN);
Якщо ви зробите це, то надсилання SIGTERM
нічого не призведе, вам доведеться використовувати SIGKILL
для завершення процесу.
Детальніше в man 7 signal
. Зауважте, що використання signal()
цього способу вважається непортативним - це набагато простіше, ніж альтернатива!
Ще одна незначна виноска - Solaris killall
намагається вбити всі процеси. Усі. Якщо ви запускаєте його як root, то ви можете бути здивовані :)
pkill
. Інша причина полягає в тому, що він поєднується з тим pgrep
, що полегшує перевірку, які саме процеси будуть вбиті, і які самі семантики краще відповідають, ніж ps | grep
.
"Кінець усім" був би killall -s SIGQUIT [process name]
. Якщо ви хочете фантазійне рішення, визначтеся alias endall='killall -s SIGQUIT'
.
SIGQUIT
це як зробити процес abort(3)
: він скидає ядро, а потім вбиває процес. Це ні в якому разі не приємніше / ніжніше / добріше, ніж SIGTERM
для дефолту killall
.
SIGQUIT
(або ще краще SIGINT
), можна поводитись «м'якше», ніж це SIGTERM
, але це залежить від програми. Неопрацьований будь-який з них спричиняє негайне припинення.