Kinder / gentler / subtler эквивалентная альтернатива killall (например, «endall»)?

16

Как завершить все процессы с тем же именем более мягким способом, чем killall ? Я не хочу прерывать процессы, но оставляю им время для правильного выхода.

См. также:

Как убить процессы в Ubuntu?

В системном мониторе , в чем разница между процессом Kill и конечным процессом?

Почему нужно использовать killall (иногда?)? дважды?

tl; dr

    
задан nutty about natty 21.09.2015 в 13:23
источник

3 ответа

42

1. 'killall' уже хорошо (SIGTERM)

killall по умолчанию отправляет SIGTERM . Это уже хороший подход, который оставляет приложениям возможность очистить себя. «Иди, иди, прямо сейчас!» Подход состоит в том, чтобы отправить сигнал SIGKILL , который требует указать это как вариант для killall . Из Библиотека GNU C: Сигналы завершения :

  

Макро: int SIGTERM

     

[...] Это нормальный способ вежливо запросить завершение программы.

2. Системный монитор «Конечный процесс» одинаково хорош (SIGTERM тоже)

Вы связались с вопросом о системном мониторе GNOME. Это также использует SIGTERM для действия «Завершить процесс» (и я понимаю, что я противоречу ответам на этот вопрос). Вы можете найти его в исходном коде, чтобы убедиться сами:

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 - номер сигнала. Сигнал 15 равен SIGTERM . И System Monitor использовал SIGTERM задолго до того, как был задан и задан другой вопрос.

Техническое добавление (в ответ на комментарий)

Просматривая представление Github git blame , приведены изменения, которые были сделаны в отношении того, как сигналы указаны в исходном коде системного монитора GNOME:

383007f2 24 июля 2013 г. Заменен дублированный код для отправки сигналов с параметрами GAction < br> 0e766b2d 18 июля 2013 г. Всплывающее меню процесса порта для GAction
97674c79 3 октября 2012 Избавьтесь от структуры ProcData
38c5296c 3 июл 2011 Сделать равномерным отступы в исходных файлах.

Ни один из них не изменился с SIGQUIT на SIGTERM , а последний был до того, как был задан связанный вопрос.

    
ответ дан hvd 21.09.2015 в 13:49
источник
5

Ответ на @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... (используя // в начале строки), чтобы удалить обработчик сигнала, затем запустить и отправить сигналы снова. Вы должны уметь видеть эти разные выходы:

$ ./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, вы можете быть удивлены:)

    
ответ дан Roger Light 21.09.2015 в 16:56
2

«Конец всех» будет killall -s SIGQUIT [process name] . Если вы хотите причудливое решение, определите alias endall='killall -s SIGQUIT' .

    
ответ дан Jos 21.09.2015 в 13:29