Киндер / нежнее / тоньше эквивалентная альтернатива killall (например, "endall")?

17

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


Смотрите также:

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

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

Почему killall (иногда?) Нужно применять дважды?

ТЛ; др

сумасшедший о натти
источник
1
И твой вопрос?
Pilot6
@ Pilot6 перефразировал: что такое "более мягкая" альтернатива killall?
Сумасшедший о Натти
1
Что такое "мягче"?
Pilot6
@ Pilot6 «мягче» в смысле «Конец» системного монитора против «Убить»
сумасшедший по поводу натуры

Ответы:

43

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


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

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

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

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

HVD
источник
7
+1 за ссылку на исходный код! (+2 за противоречащие «общепринятые», как это было;)
ореховое о Natty
Ну, прежде чем заявить, что вы противоречите ответу: проверяли ли вы, что все версии исходного кода используются 15? Возможно, в какой-то момент он был изменен, поэтому старый ответ может быть на 100% правильным по сравнению со старой версией.
Бакуриу
1
@Bakuriu Я так или иначе не согласен с этим ответом, но, честно говоря, я постараюсь не забыть проверить это в следующий раз.
HVD
@Bakuriu в исходном дереве git git grep 'SIGQUIT'ничего не раскрывает. Ничего, связанного с сигналами, не найдено git grep '>3<'ни для одного. Я делаю вывод, что, скорее всего, gnome-system-monitor никогда не использовал SIGQUIT.
Руслан
@Ruslan git grepищет только текущее дерево, а не всю историю. Я использовал git blame(фактически эквивалент Github), чтобы копать немного глубже, но все еще ничего.
HVd
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... (используя 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()таким способом считается непереносимым - это намного проще, чем альтернатива!

Еще одна второстепенная сноска - на Солярисе killallделается попытка уничтожить все процессы. Все они. Если вы запустите его как root, вы можете быть удивлены :)

Роджер Лайт
источник
1
Это одна из причин, по которой я предпочитаю pkill. Другая причина в том, что он соединяется с pgrep, что упрощает точную проверку того, какие процессы будут убиты, а какая сама семантика соответствия лучше, чем ps | grep.
Random832
1

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

Jos
источник
13
SIGQUITэто как процесс abort(3): он сбрасывает ядро, а затем убивает процесс. Это ни в коем случае не лучше / мягче / добрее, чем SIGTERMпо умолчанию killall.
Руслан
3
Для процесса, который обрабатывает сигналы SIGQUIT(или даже лучше SIGINT), его можно обрабатывать более «мягко», чем это SIGTERM, но это зависит от приложения. Необработанные, любой из них вызывает немедленное прекращение.
R .. GitHub ОСТАНОВИТЬ ЛЬДА
1
Это отличная идея, если вам нравится чистить основные файлы на всем диске.
Нейт Элдредж,
2
@Qix: Одна вещь, которая варьируется в зависимости от сигнала, это то, создает ли он основной файл или нет в действии по умолчанию (если не обрабатывается приложением). Вероятно, предпочтительнее использовать сигналы, которые не генерируют файлы ядра.
R .. GitHub ОСТАНОВИТЬ ЛЬДА
1
Стоит отметить, что ubuntu по умолчанию устанавливает ограничение размера файла ядра равным 0, поэтому SIGQUIT фактически не создаст файл ядра (если он не обработан), если вы не измените ограничение.
Роджер Лайт